Isn't that the very definition of hype? :^)
We can't hide in a cave to build everything in secret until it's ready because otherwise we wouldn't have the money to pay contributors, or we would be forced to get funding through other means (I mention that point in the blog post). And while we do want to be in the open, you can see that in my writing I never talk about a future that's distant and completely unproven. Even the most forward-looking stuff I mention, like incremental compilation, has at least had a proof of concept to show that it's not pure fiction.
I'm obviously biased, but I think we're in a pretty good spot when it comes to gathering public interest vs getting things done.
Can you see though how this model can cause a lack of trust in external observers? Your development model is reliant on attracting attention to drive funding. There are some major incentive problems here. I want to be clear that I am not suggesting that you are deliberately doing this but your model actually incentivizes building a lower quality product. You just need to make something appealing enough that people start using it and then, once they are invested in the language, some of them may be willing to pay you to fix the issues they find or build new features that would be useful to them. If the language didn't have issues, there would be no reason to pay you to fix them.
I know I will likely get downvoted for this but I believe in what I say.
Yes, what alternative do you recommend? VC funding? You think any other financing model would result in being less reliant on attention as opposed to enhancing the effect?
> I want to be clear that I am not suggesting that you are deliberately doing this but your model actually incentivizes building a lower quality product.
You're writing this in a discussion about us having just spent two years reimplementing the compiler to pay tech debt, instead of doing any of the things that you mentioned.
I have to admit that your post smells a bit of concern trolling, especially considering that we've seen a bunch of that in the last few weeks.
As also a 3rd party observer, there is an obvious partial counter to the argument that you made. In the case of free and open-source, people are investing money or time because they believe in the product and its potential usefulness. That the product will deliver, for all people invested and for all users, is clearly unrealistic. There is no such thing as a "sure thing". It's more a matter of if the product delivers for enough people. And if anything, if unsatisfied, people are free to jump to the next candidate or savior that floats by.
I think the more valid aspect of the point presented, is the lack of trust or suspicions coming from when the hype is paid for and doesn't come from the grassroots and actual users. To include, negative propaganda campaigns targeting competing languages.
> If the language didn't have issues, there would be no reason to pay you to fix them.
All languages will have issues. I've always found this curious about people having such expectations. Maybe the argument is more valid in terms of the total amount of issues and bugs, but then that would need to be a fair and relative comparison to other languages. There is no such thing as a bug-free perfect language. While other parts of your post were "more valid" or at least points worth considering, I think on this point, it kind of fell off the mark.
> I know I will likely get downvoted for this but I believe in what I say.
Odd, that's exactly what happened. The tribalism is arguably too severe, which may relate to the money involved, that the downvoting is so predictable.
I think Zig is getting too much hype. It's unfortunate because Zig could have potential, but hyping something before it's ready is a recipe for alienating early adopters and killing progress towards popularity.
The worst part of it is that I've heard people say that they've got Zig in production; with all of the bugs in the compiler, they are apt to get burned, and too many burns will lead to putting out the fire and rewriting.
It doesn't help that (in my opinion) there is confusion regarding basic things about Zig. [1]
[1]: https://gavinhoward.com/2022/04/i-believe-zig-has-function-c...
> The misunderstanding that post makes is that function coloring refers to at compile time.
The original function colors post referred to runtime, so you're wrong.
> In other words, in Zig you don't need to write two versions of a function to use it in async vs sync context.
This is correct, if you only care about compile time.
> Obviously the functions will have different runtime representations, so if you do something that cares about runtime calling conventions or w/e then yes you do need to worry about how the function is used, which is unavoidable.
So you admit that Zig does have function colors?
Also, according to the actual Zig documentation, which I quote in my post, there is only one version of every function; if a function is used in an async context, even if it is sync otherwise, the compiler makes the function async and continues on its merry way, so there is only one runtime representation of a function.
Here's the quote from the documentation:
> Zig infers that a function is async when it observes that the function contains a suspension point. Async functions can be called the same as normal functions. A function call of an async function is a suspend point.
Saying that Zig does not have function colors because it hides them at compile time is a little disingenuous, in my opinion. It still has them, but like a statically-typed language with type inference, it just hides that fact, but only at compile time.
Not to impugn your character, but I feel the same way about the points you're making.
> So you admit that Zig does have function colors?
Not in any meaningful way, no. Again, the runtime representation of async vs sync functions is unavoidably different, and has nothing to do with the language. The fact that Zig lets you write one function definition that can be called in sync vs async contexts (unless you're specifically choosing to do sync vs async things) is what it means to be colorless!
> Also, according to the actual Zig documentation, which I quote in my post, there is only one version of every function; if a function is used in an async context, even if it is sync otherwise, the compiler makes the function async and continues on its merry way, so there is only one runtime representation of a function.
I dunno if that's accurate? Someone with more knowledge of Zig internals would have to confirm, but I assume if the same codebase uses a function in each context it'll be monomorphized into the specific version needed, same as generics. I don't think that's contradicted by what you quoted.
It's not, your understanding of async in Zig is sound. I would even add that in the blog post in question (my post, the one ghoward is replying to in his) I don't even dare to describe Zig as colorless, in fact I say colorblind.
Then perhaps there is something wrong with the language reference?
> I don't even dare to describe Zig as colorless, in fact I say colorblind.
Doesn't that mean my blog post is right?
But my biggest beef is that people, including GP, used your blog post to then claim Zig is colorless. I mean, GP did it in GP.
Your blog post is full of wrong information. I tried to explain to you what was wrong when you first posted it (so you can refer to those comments, if you want), but you keep seeing this as some kind of philosophical debate, and I have no interest in having this debate.
As I said to you already in the past, I just write software with Zig async and it works. Up to you what you want to do with your free time.
Accuracy is important in the marketplace of ideas, and especially in programming. Software is too buggy already, and it would only add more bugs to have programmers not understand the languages they use.
> I made this same observation in the past, it never satisfied you.
Yes, you made that same observation, and I appreciate that. But as @kbd so unintentionally demonstrated, people still believe that Zig is colorless. I want to dispel that notion completely.
I think you are not adding to the problem, and that is great. But the notion is still there.
> Your blog post is full of wrong information. I tried to explain to you what was wrong when you first posted it (so you can refer to those comments, if you want), but you keep seeing this as some kind of philosophical debate, and I have no interest in having this debate.
Here is all of the comments you made on Hacker News on the comments [1] about my blog post.
> That's exactly it. It just enables code reuse. You still have to think about how your application will behave, but you won't have to use an async-flavored reimplementaion of another library. Case in point: zig-okredis works in both sync and async applicatons, and I don't have to maintain two codebases.
> https://github.com/kristoff-it/zig-okredis
> I thought using "colorblind" in the title of my original blogpost would be a clear enough hint to the reader that the colors still exist, but I guess you can never be too explicit.
and
> That's how it works in Zig. Calling an async function like this will also await it.
The closest thing to "explain[ing] to [me] what was wrong when [I] first posted it" is probably that first comment, which was in reply to
> I may be totally wrong with this assumption, but the way I understoo[d] Zig's color-less async support is that the compiler either creates a "red" or "blue" function body from the same source code based on how the function is called (so on the language level, function coloring doesn't matter, but it does in compiler output).
> The compiler still needs to stamp out colored function bodies because the generated code for a function with async support needs to look different - the compiler needs to turn the code into a state machine instead of a simple sequence).
> It's a bit unfortunate that red and blue functions appear to have a different "ABI signature", but I guess that's needed to pass an additional context pointer into a function with async support (which would otherwise be the implicit stack pointer).
(Original comment at [2] by flohofwoe.)
So if anybody explained anything, it's flohofwoe.
But flohofwoe's comment goes directly against the the language reference, so it's hard for me to believe.
The language reference says that sync functions are turned async if they call async functions. This implies virality of async on functions, which implies that many functions are definitely async-only.
If the compiler does something different, which it would have to if it actually makes two different versions of each function, then the language reference is wrong. Like I said, accuracy matters, so I would also like to see changes in the Zig language reference about this if that's the case.
> As I said to you already in the past, I just write software with Zig async and it works.
Yes, you write working software in Zig async, but you understand it better than most. People who go to the language reference and write based on that may not be able to write working software with Zig async as easily as you.
> If the compiler does something different, which it would have to if it actually makes two different versions of each function, then the language reference is wrong. Like I said, accuracy matters, so I would also like to see changes in the Zig language reference about this if that's the case.
To be clear, do you expect this function
fn invokeFoo(a: anytype, b: anytype) @TypeOf(a) {
return a.foo(b);
}
to have only one representation at runtime, and for that one representation to be either async or not async?- flips I/O functions to evented mode, both by setting the correct flags when creating, say, a socket, and also by having `suspend` and similar keywords in the winning branch of some comptime conditional statements, causing the functions in question to become async also in the language.
- instead of directly calling into main at program start, it starts an event loop and schedules main on it
This is all userland stuff based on a convention, none of this is ingrained in the programming language itself and it could very well be that in the future things will have to be done in a more explicit way.
Async functions are single frames (as opposed to being green threads).
Again, the original post about function colors talks about runtime, so how could I be disingenuous about that?
> Not in any meaningful way, no. Again, the runtime representation of async vs sync functions is unavoidably different, and has nothing to do with the language. The fact that Zig lets you write one function definition that can be called in sync vs async contexts (unless you're specifically choosing to do sync vs async things) is what it means to be colorless!
I mean, this would be true if it were true. But I tried to use the "blue" function in my examples in both contexts, and it didn't work. In fact, it didn't even work to use the "red" function in both contexts.
> I dunno if that's accurate? Someone with more knowledge of Zig internals would have to confirm, but I assume if the same codebase uses a function in each context it'll be monomorphized into the specific version needed, same as generics. I don't think that's contradicted by what you quoted.
I worded this completely wrong, so let me fix that. I should have said,
> if an async function is used in a sync context, the compiler makes the context async and continues on its merry way, so there is only one runtime representation of the function that was the context.
But it means that the sync function that was the caller is made async no matter what because it calls an async function. So there is no monomorphization; there cannot be since there is a call to an async function that always makes an async context that always turns the caller async.
In most programs you end up with all async functions or all non-async functions in a specific context, so if someone handed you a pointer you'd have no problem knowing which calling convention to use. But if you actually end up not knowing, because you really do have a mix of different types of pointers, you could call all of the pointers via the @asyncCall builtin. I have done this successfully, but I'm not actually sure whether it worked by having a pointer to a non-async function at runtime or by specializing the function that I was using that did not need to be async (because its body and callees did not use await or suspend) to use the async calling convention. Or you could use a tagged union of multiple function types and make your own `call` method for that union. This is pretty weird though, because you'll end up requiring the end user to provide storage for the async frame even when the function isn't async and doesn't actually need that storage.
If you search headline with Zig which reached HN front page, you will only see about 1 - 2 per month. Compared that to Rust, which isn't even as popular as it once was.
But still, I do wish the Zig community could quiet down a little bit. It would be nice if decent zig submission hit HN front page once every two months. Keeping the interest alive but not too much so people felt it is over hyped.
We will have a November Release soon and I can guarantee it will hit HN front page again.