I like zig, but agree with many of the points here. A couple of thoughts below,
> Zig reference documentation badly needs examples. Can't figure out how to use std.fmt.parseInt.
While yes, Zig documentation badly needs examples, I'm not sure this particular criticism is justified. I would have thought that the usage of parseInt, was fairly obvious from the type-signature:
parseInt(comptime T: type, buf: []const u8, radix: u8) ParseIntError!T
Or, translated to C++ (and assuming the use of exceptions to return the error):
template T parseInt(const char buf[], uint8_t radix)
> Need to access myArray.items[idx] instead of myArray[idx]. I get it. But very unintuitive and requires knowledge of implementation details.
I'm 50:50 on this one. While it might be nice to hide the implementation here and have a .item(n: usize) member function, ArrayList explicitly manages a contiguous region of memory, so I don't see the problem with exposing it as a slice as part of the interface.
> Should I pass the allocator to every function? Doesn't seem great. Maybe I'm supposed to create a global? Globals are evil and feel bad.
As a rule of thumb, libraries should take allocators as arguments to their functions, while applications can either do that or create a global allocator. There is absolutely nothing wrong with using a global allocator in an application; after all it's what almost every other language does. Zig just makes that global explicit.
Globals aren't always evil.
> Zig's inability to infer type is annoying. If I create var count and return it and the function return type is usize then var count is obviously a usize.
It's not. It could be any unsigned type of smaller size than usize.