Ergonomics of ArrayListUnmanaged

In functions where it is possible to know the upper bound of added elements, the unmanaged style encourages to first reserve the needed unused capacity and then optionally use errdefer comptime unreachable to declare that no errors will happen beyond that point, followed by a bunch of calls of the *AssumeCapacity variant. I think writing code in that style (where it is possible) is good because it reduces the possible failure points, groups allocations, is explicit and doesn’t require passing the allocator or using try everywhere.

So overall I would say that: if using reserve-first happens more often, when there is only unmanaged variants in the standard library, then I prefer not having the managed variants.


Regarding the Managed(Unmanaged) in the absence of being able to automatically directly add adapted member functions*, where you don’t need to pass the allocator, having such a generic tuple doesn’t seem worthwhile to me.

Because try playlist.unmanaged.append(playlist.allocator, value); doesn’t seem easier than try playlist.tracks.append(playlist.allocator, value); with the latter you can use multiple lists that share the same allocator, give the lists meaningful names and you don’t repeat unmanaged everywhere.

*Zig doesn’t really support generating these sort of wrapper functions in a generic way, it could work via zigft library which uses platform specific assembly (part of me wants that library to become zig features, for example argument spreading as language feature, but I guess the fear is that this would allow generating layers and layers of automatic wrappers which are difficult to decipher)

I think the managed style would only be worthwhile if it was specifically adapted towards making the usage code easier and more fitting to the domain and possibly also easier to replace the underlying data structures, which are populated by that code. So I think for a more managed style it would make sense to focus on the actually needed operations (for example different ways of Adding / Removing / Batching / Filtering / Collecting stuff), basically creating a simplified API for specific operations and then underneath it would handle the unmanaged collection and allocator.

But I also think that if such a more managed interface is useful, it is quite easy to create it on the fly and then manually write some of those convenience functions, at least then those are actually fitting to the domain (and could even contain some checks or assertions), instead of over-engineered generic code.

3 Likes