Of course, don't use your own hand crafted version in Python, since one is provided with the language and it is better than the one you will likely come up with.
Still, it's interesting because it's simple. So starting from the intro of this article, if you want to go further, try to do the following to match up __builtins__.zip:
- make it lazy (yield would work)
- make it work with any iterable (iter() + StopIteration would work)
- put some type int and a docstring (so that help() gives you informations)
- accept any number of iterables (variadic parameters would work)
- make a second version that accepts a fill value (like itertools.zip_longest)
This will sharpen your python skills, and also will make you appreciate even better how much you get for free with the stdlib (not to mention __builtins__.zip is in C, so it's fast).
> will make you appreciate even better how much you get for free
This is unironically the reason I come back to Python again and again. The language itself is not my favorite: it 'should' be different. But my productivity with it is frankly unmatched.
The "zip" example is an excellent case study. The actual "zip" is by default lazy, it accepts arbitrary iterators, etc. It's the "correct" solution, unlike the one presented in the article, and I have it at my fingertips, in the standard library.
"Unironically" here means "seriously", "literally", "actually", etc. It's basically a marker that the speaker is speaking straightly and plainly, without trying to make a joke.
Yes, it's not really antonymous to "ironically" (in the narrower sense of this word) in this context.
I think it's fairly literal, there's a whole brand of humor around pretending to like things that you actually like. "I like C because of all the undefined behavior".
But this is also how word meanings shift over time. Someone will see someone else using that word and not know what it means, but then start using it, etc.
In reality most of these are really simple, the big question is how to handle end of iteration across iterators e.g. given zip(a, b) where a is shorter than b, on the last iteration will b get updated or not?
Progressing an iterator is a side-effect (a mutation).
Depending how the last iteration is handled, zip(a, b) and zip(b, a) with iterators of different sizes can have different behaviours: if a is shorter than b, a naïve implementation would update b in the zip(b, a) case, but not in the zip(a, b) case.
That reminds me of a lovely paper "How to Add Laziness to a Strict Language Without Even Being Odd" by Wadler and MacQuenn. They use "map" as their running example, but the problem is basically the same.
zip is generally implemented as a functional concept, where the iterators take values from the backing iterable structure "by const &". You can implement a custom mutating zip operation on top of the iterator protocol.
I believe masklinn is talking about whether `zip` consumes an extra element from the longer iterator on the last iteration, when the shorter iterator raises StopIteration. And the behavior might vary depending on the order of the arguments.
This is the problem with python's conflation of iterable and iterator, and maybe why so many programmers don't understand the difference when they pick up Java.
> This is the problem with python's conflation of iterable and iterator
It really is not. It’s just a natural outcome of imperative langages. If operations can have side-effects, then combinator behaviour will affect those side-effects.
You could do the same with iterables with side-effecting iterations.
It’s also perfectly logical to be able to iterate an iterator.
I was looking for a way to implement this more pythonically. And this looks great. But it made me think that if x and y are of different lengths, the last iteration might consume an element out of the longer iterator.
So I tried it with the builtin `zip(a,b)`, and indeed, if a is shorter, `zip(a,b)` consumes the same number of elements from both a and b. But if a is longer, then `zip(a,b)` consumes one extra element from a.
I don't know if this behavior is well defined, that is whether I can rely on this, or the order of evaluation of the arguments of a function is up to the interpreter/compiler, and may change.
masklinn wrote a comment in another thread about this that i didn't understand until I saw your implementation.
def myzip(*seqs):
next_yield = [None] * len(seqs)
its = [iter(seq) for seq in seqs]
should_go = True
while should_go:
for index, it in enumerate(its):
try:
next_yield[index] = next(it)
except StopIteration:
should_go = False
if should_go:
yield tuple(next_yield)
It consumes exactly the same number of elements from all sequences, unless a non-StopIteration exception occurs during the iteration.
I‘m not good in JavaScript, but reading the code, I wonder if this implementation doesn’t have an issue with truthiness in the second array. For example if you zip([true,true],[false,false]).
The minimum length approach seams to be the better one. (Without having it run anywhere.)
That was my quick reaction as well... I think it would need something like the python example below, where you first check the lengths of the two arrays/lists, and then iterate over that, and not directly over the length of the first list.
iter_limit = Math.min(ls1.length, ls2.length);
for(let i = 0; i < iter_limit; i++)...
Yes, the JavaScript implementation doesn't works if the second array contains 'false', 'null', 'undefined', '0' or 'NaN'.
Here is my implementation of the 'zip' function in modern JavaScript. It is similar to the Vlang version, but it is generic over the number of arrays :
The inclusion of Vlang is interesting. I remember that it was created together with Volt, a multi-service messenger app that never delivered. Is the language any good, and are there any advantages over more established esoteric systems languages like D, Nim, or Zig?
From a pure language perspective, not taking into account infrastructure and implementation, Vlang is currently my favorite language. It has pretty much the syntax and semantics I want in a statically compiled, strongly typed language. However, there are still too many features of the current implementations that are in reality not yet implemented or too experimental. It's still not ready for production and larger projects.
I'd say the languages you mention are substitutes according to the following mapping:
V promised a lot of stuff as ready but has undelivered most of them and people lost trust.
If V was truthful like Zig, it would be able to create a foundation.
Also a programming language will never be able to substitute another one if it is not able to call its vast number of libraries.
I agree, the table refers to the intention of the language developers and how the languages feel, it's not about real substitution. For example, D was explicitly designed as a better version of C++ and also allows you to use C++ libraries directly, and Zig is explicitly intended as a modern substitute for C.
As for V, it delivers quite well for a language at such an early stage and has a growing community. IMHO, it's a great language.
They were doing very level-headed reviews of the language at that time, found that the claims were mostly unsubstantiated, and then got blocked by the V team.
That did not inspire confidence at all, as you might imagine. I can completely understand OP when they are saying "V promised a lot of stuff as ready but has undelivered most of them and people lost trust." -- that was my view too.
-----
Again, it might be better now. The V team might have delivered in the meantime. But I can definitely see where OP is coming from.
Things might be better now, but the previous false advertisement makes it really hard to tell. For example, vlang.io claims no undefined behaviour¹, but with
struct Foo {
bar int
}
println(&Foo(voidptr(some_address_here)))
it seems to read whatever memory is at that address (which is UB in C, and V compiles to C, so...).
¹it says some overflowing can still result in UB, but that's not what's happening here; also this warning was only added in July.
I am not a "sleeper account". I posted a very calm and charitable take on my view, in it explaining that I understand OP's view. Nowhere did I smear the language, or troll, or do anything of the sort.
You on the other hand immediately label me as a sleeper account and a troll, for only mentioning a few links to a webpage. Although I can understand being defensive by default if you get trolled a lot, I don't think this is a good way to win people over. It certainly is off-putting to me.
-----
But anyway, content related: did Xe/Xena/Christine lie in their blog posts at that time? I've read other blog posts by them and those generally seem to be level headed, well written blog posts -- not spam or anything.
Next to checking out the Vlang's website, those blog posts were my only exposure to the language at the time -- as you can imagine for a new language.
-----
>> ...and then got blocked by the V team.
> This appears to be more trolling, and just distortions or lies, as a setup to unload more spam links and misinformation.
Is the image in the tweet in the last post not correct? That Xe got blocked by @v_language? Or is that not the official Twitter account?
You have to remember, I'm just an outside observer -- and all I see is a person testing the claims a language does, finding they are mostly unsubstantiated, and getting blocked in the process.
All I can say is, I'm not that poster. The names being similar is a coincidence. This being mostly an anonymous forum however, I don't have anything to prove it to you. Maybe my post history can serve as a small argument, although that can be faked/bought/hacked too.
I think it would be better to engage in open, sincere, and civil discourse about the language -- instead of labelling people that raise questions or concerns as trolls with sleeper accounts.
We don't allow single-purpose accounts on HN, nor (to widen the scope slightly) accounts that are primarily obsessed with one agenda. That's incompatible with intellectual curiosity, which is the thing this site exists for.
Since your account seems clearly in that category, I need to ask you to stop posting about this, not just now but in the future. That's not taking a side about Vlang (I have no idea!) - it's just about the intended use of HN.
> ...successfully pushed a potential new user away...
1) You are "projecting", what is your purpose and agenda.
That is your intent, as an obvious troll (who masquerades as a Rust advocate), that probably has multiple accounts or working in a concerted effort from an organization of a competing language.
2) Your agenda is very clear.
It is mainly attacks, flames, and unloading of spam on any posts or threads which mention or are concerning Vlang.
3) Your troll account should have been banned a while ago.
All of this is very clear by your disruptive flame war comment history, for all to see.
> Vlang warriors...
So PufPufPuf and jonathanstrange are also "Vlang warriors", for just casually mentioning and saying something positive about Vlang on a thread about it and multiple languages?
What actually is happening, is the mere mention of Vlang can cause various rivals and competitors to engage with troll accounts to spam the name of their competing language (in this case Zig) and unload massive amounts of misinformation, propaganda, lies, and negative disruption on threads.
Notice how it is never initiated in the opposite direction. It is nearly always advocates of specific rival languages doing this, though they kind of and sloppily try to hide their affiliation, but often slip up as apparently they can't help themselves. Their activity consists of attacking or bashing Vlang (to include spamming the same negative propaganda links), when it is positively mentioned. This is very clear from HN's post history.
To include, this spamming or trolling activity by various evangelists or paid advocates of a certain language has gone over the top on the HN site, and is now on the radar of moderators (who have mentioning it).
Please don't post in the flamewar style to HN. Regardless of how wrong someone is or you feel they are, it's not what this site is for, and it destroys what it is for.
You did it a whole bunch in this thread, unfortunately. If you wouldn't mind reviewing https://news.ycombinator.com/newsguidelines.html and taking the intended spirit of the site more to heart, we'd be grateful.
Haha, alright man. Still with the alt/sleeper account. Cool. I'm just some guy from the Netherlands trying to get a calm conversation going. I don't feel like any of my posts have been in any way inflammatory.
You seem way too defensive to have any useful conversation with, so I won't bother any more. Good luck with vlang!
To give you some background on why your original post might've been considered inflammatory - the author of the blog you shared has openly said "V is something that should be ignored until it dies into obscurity":
> the author of the blog you shared has openly said "V is something that should be ignored until it dies into obscurity":
I didn't know this -- that's very harsh, and I don't agree at all. I see that that comment was made after the reviewing blog posts, however. I can get that the relation between V and them has soured.
That's the one I initially replied to, sharing my view as an outside observer. It would probably serve V well to handle such popular blog posts in some way. Like put up a blog post refuting the points in the article, and then link to that or something. Something to undo the damage to the language's image by those posts, and (re-)inspire confidence.
The other way is probably to be "so good they can't ignore you". That would be great, always good to have more great tools.
> My advice is - check out the language and make up your own mind. In the end this is a tool, not a football club.
I completely agree -- and people should try it for themselves. I guess my point is mostly that if the community's exposure to a language is those blog posts, they won't be inclined to try it. And if those blog posts don't get handled in a graceful and confidence inspiring way, the community won't "update" its view of the language.
Hey Tozen, are you alright? It might be good for you to take a step back and relax a bit.
I have been nothing but civil and open-minded, I have not smeared vlang in any way, I have merely been asking questions as an outside observer.
You, on the other hand, have been aggressively defensive, and have been projecting an almost paranoid "everything and everyone is against vlang" attitude. I almost start thinking that you are the one trolling me.
If not, I sincerely hope you will take a step back and assess the situation and yourself -- and try to relax a bit. No single programming language is worth getting this wound up about.
Please do not post flamewar comments to HN, regardless of how wrong someone is or you feel they are. It's not what this site is for, and it destroys what it is for.
D and Nim are great mature languages. If you think they're suitable for the domain you're working on and reach out for either of them, you're not gonna go wrong. They have large communities and you'll easily find answers to your questions.
I wouldn't call Zig established, though. Zig's compiler still crashes on valid code and compared to V it still doesn't have an online playground, a package manager, hot code reloading, a REPL, etc. even though it's twice as old.
V's syntax is similar to Go. However under the hood V differs from Go. For example:
- V has compile-time memory management similar to the Lobster programming language.
- V has zero-cost interoperability with C.
Check it out and decide for yourself. If you already know Go, you can learn V in an afternoon.
Interestingly, the post says "JavaScript [...] has tail call issues", but at least the Elixir algorithm is not tail recursive and will blow up with inputs that are too big.
Here's a tail-recursive function. To be honest I would have started writing this version first, the acc pattern is ubiquitous. Sorry for the mistakes, I'm on mobile:
def zip(a, b) do
zip(a, b, [])
end
def zip([], _, acc), do: acc
def zip(_, [], acc), do: acc
def zip([a | a_rest], [b | b_rest], acc) do
zip(a_rest, b_rest, [{a,b}|acc])
end
Also, there's Enum.zip/2 in the standard library, with the bonus that it works with any Enumerable type (lists, maps, lazy streams, etc,)
Sure, but if we want to highlight other languages' lack of tail call support, maybe we should showcase that support in those languages that do support it. :)
The JavaScript one is incorrect. It should use the length of the 2nd list rather than stop at the first falsy value in it.
That's where I stopped reading. Even going in, I wondered doesn't each of these languages already have a function in stdlib or a de-facto package with it?
zip is useful to have as a library function in a Lisp dialect in spite of being easily able to compose it with mapcar and list.
It comes up fairly often in macros. E.g. you have gens, a list of gensyms, and exprs, a list of expressions, and body, a list of forms that refer to the gensyms:
Of course, don't use your own hand crafted version in Python, since one is provided with the language and it is better than the one you will likely come up with.
Still, it's interesting because it's simple. So starting from the intro of this article, if you want to go further, try to do the following to match up __builtins__.zip:
- make it lazy (yield would work)
- make it work with any iterable (iter() + StopIteration would work)
- put some type int and a docstring (so that help() gives you informations)
- accept any number of iterables (variadic parameters would work)
- make a second version that accepts a fill value (like itertools.zip_longest)
This will sharpen your python skills, and also will make you appreciate even better how much you get for free with the stdlib (not to mention __builtins__.zip is in C, so it's fast).