> For loops are a bit strange too - you write for (items) |item| {}, which means you specify the container before the per-element variable. Mentally I think of for as for something in many_things {} and so in Zig I constantly had to write it wrong and then rewrite. Also you use the | character in Zig quite a lot, and while this may just be a problem with Apple UK keyboards, actually getting to the | character on my laptop was uncomfortable. When doing C/C++ or Rust, you use the | character much less and so the pain of writing the character was something I never noticed before. Jonathan Blow has gone on the record to say that with his language, Jai, he spent a lot of time working out how easy it would be to type common things, such that the more common an operation in the language, the easier it would be to type.<p>I've written much more "Jai" than Zig but this is one of the things that stuck out to me the most in Zig's syntax as being strange. in "Jai", for loops iterate over arrays, ranges (0..10), or anything else that has a for_expansion defined for it. implicitly, "it" is the iterator and "it_index" is the index. to for-loop over an array, you simply write<p><pre><code> foos: [..] int;
for foos { /*...*/ }
</code></pre>
if you don't want to use it and it_index, likely because you're nesting loops, you write<p><pre><code> for foo: foos { }
for foo, foo_index: foos { }
</code></pre>
this has some very nice properties in addition to relative terseness: when you want to iterate over something, which is something you do all the time in all kinds of contexts, you just write "for foos do_something_to_foo(it);" suddenly you find you need to use something other than the implicit it/it_index, so you just change it to "for foo: foos do_something_to_foo(foo);" maybe when you're "sketching out" your program code, "foos" is just an array of ints, but as you flesh things out further, you realize you want it to be a custom data structure with additional information that can nonetheless be iterated over as if it were still an array. you simply write a for_expansion for the new data structure:<p><pre><code> Foo_Storage :: struct {
items: [..] int;
additional_info: string;
}
for_expansion :: (using storage: *Foo_Storage, body: Code, flags: For_Flags) #expand {
for `it, `it_index: items {
#insert body;
}
}
foos: Foo_Storage;
for foos { /*...*/ } // the loop interface remains unchanged
</code></pre>
I completely agree with the author here in that I appreciate this approach as opposed to Zig's, with regards to making it as easy as possible to write basic constructs ("loop over some stuff") that you're going to be writing a lot, in a lot of different places, in a lot of different contexts, all the time, constantly. this is the one area in which this language and the design ethos behind it is completely different from Zig and other contemporaries—it balances power and simplicity with developer ergonomics quite nicely.