Is it still a feature of the language that it's rules are simple enough so you don't need to debug your knowledge of the language?
Neither this `inline case else` nor the async/await make sense to me. Granted, I don't use the language, but when I tried to read the documentation/tutorials to understand them, I couldn't. With async/await, I read the docs then tried to debug my understanding and the small amount of code I wrote didn't work the way I expected.
This inline else example makes sense when you stop and think what it is doing, but it is in no way intuitive.
Taken at face value, why is it switching on self with no case whatsoever? Why does the else case need to be inlined? This is trying to be smarter than it needs to be.
The fact that you ask why it needs to be inlined means you haven't understood how the feature works. If you did, you'd be a fan. It's a general mechansim that fits Zig perfectly, along with inline for and while.
don't know about the language rules, but I've had to wait for the explanation to understand what was about to happen. Naming is hard, d'oh, but I feel this could have a better name. "inline" does not trigger my brain in a way a "comptime_expanded" or "comptime_generator" would, e.g.
I believe andrew and loris have been with zig for long enough to have their own bias and no longer be aware of it, thus I believe it's the newcomers' job to hold up the simplicity design premise now...
"inline" constructs all behave kinda the same way in Zig, like I've explained in the article. Once you're used `inline for` etc, it all works in a fairly homogeneous way.
This article was mostly about pointing out how `inline else` lends itself really well to writing tagged union interfaces, I would expect anybody who actively writes Zig and has metaprogramming experience to not have much trouble using it.
That's what I mean with you having developed a bias and no longer being aware of it [no insult intended] ;) If you know the concept in that language and its name-tag, then it's no longer confusing, just as lisp macros aren't anymore once you grokked them. As a language in development, I would hope the on-boarding process from people with a different background would be designed to be as smooth as possible. IMO, someone coming from a different, popular systems programming language will probably have quite a different expectation what "inline" means - I know I do. Maybe finding an alias/new name for "inline" here can be considered before a "1.0".
Sure, I don't mean to claim that what inline does is self-evident. This article was really meant for people in the Zig community and in some sense it's unfortunate it reached the front page of HN.
> Maybe finding an alias/new name for "inline" here can be considered before a "1.0".
The Zig syntax has been drifting for some time and it is not in a good place.
I am afraid that the designers are blind to it because they are using it every day.
I am also afraid that once a lot of code and libraries are written, it will be difficult / impossible to change the syntax, it might already be too late.
I love Zig but the syntax quirks might considerably slow its adoption.
Why isn’t the compiler just doing inline whenever possible? Why is it a user-facing feature of the language, it looks like it should be a compiler optimization to me.
Inlining (in the C/C++ sense of the term) is not always preferable.
On top of that, in this specific case, `inline` has a Zig-specific meaning that pertains to generics and metaprogramming in a way that has not much to do with the C/C++ use of the term.
The programmer might know more than the compiler about which things should be expanded at compile time and which things should not. Zig is intended to be able to be used to generate optimal code.
But "inline" is routinely used in C in "inline functions".. I don't think anyone with a decent amount of experience with C would have trouble quickly seeing what inline means in Zig, and those people are the primary target audience for Zig.
Makes enough sense to me, although I was using Zig years ago.
An inlined function is a function that is not called in the traditional sense and instead its effects are replicated as though the function code had been written at the call site.
With `inline for` and `inline while`, the for loop isn't run in the traditional sense and instead is unrolled as though each instance of the loop had been written separately.
With `inline else`, every possible instance not covered by a `case` is expanded as though it had been written separately.
It's a little weird to C programmers only because C doesn't expand the concept outside of functions.
> I believe andrew and loris have been with zig for long enough to have their own bias and no longer be aware of it, thus I believe it's the newcomers' job to hold up the simplicity design premise now...
Zig aside, that's an astute observation in general. I think this is an issue in Python where the old guard that have been part of the project for decades and are extreme experts have gotten bored and started cramming in new language features.
The funny thing is async/await is actually fairly easy to understand (IMO a bit finicky to use, partly because manually managing resources with that control flow is tricky, partly because of bugs that need workarounds pre-1.0), but the docs aren't stellar, so you have to experiment a bit or ask the community how certain code is supposed to be have.
As one example, here's a description of "suspend" straight from the docs:
> At any point, a function may suspend itself. This causes control flow to return to the callsite (in the case of the first suspension), or resumer (in the case of subsequent suspensions).
That description isn't quite right though. Control flow returns up the call-stack to the most recently executed async-aware bit of code. In particular, that'll either be the most recent _async_ callsite or whoever last resumed this function. It's precisely those semantics which enable one to write a nice event loop API, but the docs tell you something different.
Saying that aloud, I should probably just file a PR and fix that. Off to $WORK soon, but that sounds like a good this-evening problem if nobody grabs it first.
The 'inline switch else' seems easy, no? "inline switch" should be self-explanatory. It expands at compile time like inline for loops or inline functions.
It is somewhat unique that the switch case gives you a reference to what you matched with |x|, but isn't it essentially just shorthand for self.x? And that |x| is necessary when you want to do self.x.talk() where you don't know x
I can agree that async/await is tricky to understand properly. I managed to use it to write some nice code for a demo of a Verilog simulator, but it took a few tries to get it right, because async/await/suspend/resume definitely isn't intuitive to start with. Once you understand it the rules are quite simple though. I'm sure a well written tutorial could make most people understand it.
And it depends what you're trying to do. Using suspend and resume correctly can be hard. But most of the time that will be done by people writing libraries, and when you have an async aware library and an event loop, using just async and await isn't that hard.
Zig is a new language that isn't really finished. Documentation is sparse and they're still making breaking changes. To me, Zig is a very simple and concise language, much simpler than C in many ways (we're just used to C's quirkiness), and I'm sure when it's stable and there's better documentation and tutorials it'll be easy for most people to get a thorough understanding of it quickly.
> but isn't it essentially just shorthand for self.x
At least in the `else` prong of the switch, if you want to do anything with the value you have to capture it, because `self` will be the union type, not the particular type within the union.
I've previously asked about whether this could be done away with, like if you write `if (x != null)`, could that create a scope in which x refers to the non-null value in rvalue-ish contexts but to the nullable value if you want to set it to null? Some compilers like Sorbet do this and call the feature "type narrowing." It seems like it is a bit too magical to make it into Zig though.
Neither this `inline case else` nor the async/await make sense to me. Granted, I don't use the language, but when I tried to read the documentation/tutorials to understand them, I couldn't. With async/await, I read the docs then tried to debug my understanding and the small amount of code I wrote didn't work the way I expected.