I’m wondering if there is a way to specify an allocator in some context without always having to pass the allocator to every function. A dynamic variable binding maybe, but I’m not sure how the function would handle an optional allocator parameter. Perhaps this would go against the Zig philosophy of avoiding unexpected behavior, but such a feature done right would seem better to me.
It's almost always a mistake to take the convenience of not having to pass an allocator over the flexibility of passing one. Testing, optimization via different allocators, etc. all become much easier to work with if you just make it a hard rule that anything that allocates takes an allocator.
It's impossible to misuse a function if it takes all its dependencies as arguments, etc..
With that said, I create structures that embed their allocator(s) and use them for their whole lifetime, with the rule that all their allocations have to come from the embedded ones or ones passed into methods (usually I don't mix argument allocators & stored ones, but this isn't a hard rule).
You could surely come up with a scheme of that kind in your application. To make it as simple as possible, you could simply have a global variable with the allocator you want to use, and pass a reference to it to every stdlib function you use; nothing stops you from doing that.
The explicitness is supposed to be respected by libraries, so that then the writer of the final program can enjoy maximum flexibility.