← Back to context

Comment by bunderbunder

16 hours ago

But here I feel like we’re at risk of heading down the same old doom spiral that plagues any conversation about programming languages when people try to treat it as a competition: getting pedantic about what’s technically possible in a language. It’s much more interesting to talk about how a language wants to be used.

So, in the case of Zig, every function that wants to be able to allocate or deallocate heap memory needs an explicit reference to an allocator. That means that you can tell whether a function might allocate memory from its signature. It also means that changing a function so that it can allocate is explicitly a breaking change.

That’s a really interesting design decision. And the reasons why someone would or would not want something like that baked directly into the language are so much more interesting than bickering about how technically with proper discipline you can have that kind of control in any non-GC language.

> That means that you can tell whether a function might allocate memory from its signature.

In practice that's not the case, as many objects own a reference to their allocator. It's still explicit, but it might be hidden in the signature, especially if you have some sort of interface that can take an allocating and a nonallocating data structure alike.

I agree with you, but it’s not baked directly into the language? It’s just a convention and a shared trait?

  • Not original commenter but the reality with zig is a little in between being simply convention vs. a language requirement. Is it a language requirement? no.

    However, there's no global allocator in zig. You simply cannot call the language's equivalent of malloc() because it doesn't exist - at least not as a global symbol. That leaves you with three choices: 1) Define a global allocator; is a valid choice and would make a zig program more like C, C++ or Rust in terms of not having to think about scope-level allocation patterns 2) Pass an allocator into that scope (this is the community convention) 3) Create/instantiate an allocator itself inside that scope

    (1) would be valid, though may not be idiomatic; global allocator like malloc becomes an opt-in

    (2) Expensive and inefficient for most scopes, though not all.

    (3) cheap, idiomatic but potential for noise/boilerplate

    • > However, there's no global allocator in zig. You simply cannot call the language's equivalent of malloc() because it doesn't exist - at least not as a global symbol.

      I mean std.heap.page_allocator is global, and there's only the one, and you can call it from wherever (just as you can malloc). Same with std.heap. c_allocator, which is... malloc! you can also create your own global allocator.

      Don't do this in libraries ofc or the ghost of Andrew Kelly will haunt you in hour sleep.