←back to thread

200 points jorangreef | 5 comments | | HN request time: 1.077s | source
Show context
logicchains ◴[] No.24293046[source]
I work in HFT, and one of the key concerns when writing low-latency code is "is this code allocating memory, and if so, how can I stop it?" Zig is the perfect language for this use case as none of the standard library implicitly allocates, rather for anything that allocates, the caller must pass in an allocator. The stdlib also provides a handy arena allocator, which is often the best choice.

This is a huge advantage over C++ and Rust, because it makes it much harder for e.g. the intern to write code that repeatedly creates a vector or dynamically allocated string in a loop. Or to use something like std::unordered_map or std::deque that allocates wantonly.

replies(8): >>24293328 #>>24293382 #>>24293469 #>>24293919 #>>24293952 #>>24294403 #>>24294507 #>>24298257 #
vmchale ◴[] No.24293952[source]
Linear types would be even better though. Still safe like Rust.
replies(2): >>24296793 #>>24297019 #
klodolph ◴[] No.24296793[source]
I also wish that Rust had linear types, it would make a lot of FFI easier without resorting to unsafe{}.

With linear types you can guarantee that a destructor is run, so you can create objects with lifetimes that are not only bounded from below, but bounded by above. There are some common patterns in e.g. C libraries that rely on this--for example, you might register a callback on an object, and you want to assert that the object's lifetime is shorter than the callback's (so the callback is never called outside its lifetime).

Since Rust doesn't have linear types, you have to use unsafe{}.

replies(1): >>24297225 #
1. nextaccountic ◴[] No.24297225[source]
What about making the object borrow from the closure?

This can be accomplished by a method that consumes the object and returns the closure (which now owns the object), and a closure method's that borrows the object back from it.

replies(2): >>24298141 #>>24298872 #
2. samatman ◴[] No.24298141[source]
I'm not 100% confident I follow, but this sounds like one of those backflips Rust programmers do to satisfy the borrow checker.

As in, you wouldn't write the code this way if you didn't have to. You do get memory safety in return... but you can see where the desire for a more eloquent approach might arise.

replies(1): >>24300381 #
3. klodolph ◴[] No.24298872[source]
> What about making the object borrow from the closure?

That doesn't actually guarantee that the closure will outlive the object. You would need linear types in order to do that, and Rust does not have linear types.

In the particular API I'm working with, you pass the closure in to an object when you create it, and you have to make sure that the closure outlives the object. The only way to do that within the Rust type system is by making the closure 'static, which is... less than ideal. So you use unsafe{} instead.

This is because any object may outlive its specified lifetime. Lifetimes are only lower bounds. So if I have lifetimes 'b and 'a, and 'b : 'a, this only means that the LIFETIME 'b must be at least as long as the LIFETIME 'a, but any particular object with lifetime 'b may live arbitrarily long, as long as it lasts at least as long as 'b. And any object which is 'a may last arbitrarily long, but at least as long as 'a.

4. gautamcgoel ◴[] No.24300381[source]
For a moment I thought Sam Altman was spending his time reading random HN forums and commenting on the intricacies of Rust coding. Took me a minute to catch the missing "l" in your handle ;)
replies(1): >>24301105 #
5. samatman ◴[] No.24301105{3}[source]
haha I'm not sama and have been using this handle, and variants, for longer than he's been alive.

But you're not the first to think so!