I’m actually looking into learning zig. The deal is that I don’t really have an use case for it. My work vastly prioritizes development speed over actually fast programs
i like the way zig interfaces with c. even though it’s a “newer” (not 1.0) language you can import native c which means you have access to already really fast libraries. the build script and macros are the same language you write your code. the best part is you can interface with normal code (not unsafe) and can create boundaries where sure in the c side you can’t enforce memory safety, but where you interface you can convert into memory safe types.
to talk more about memory safety i think rust does a great job, however there are some inconsistentcies where a lot of memory allocations can throw out of memory errors that will crash the app whereas zig you could gracefully handle it. this is probably more important for lower level things like kernel than an app where not recovering means everything goes down.
honestly i wish there was an opt in borrow checker as some patterns are easily expressed, but honestly i would opt out for async code as it just gets verbosely over-declarative imo. also the new async in zig is really really cool.
rust does a great job, however there are some inconsistentcies where a lot of memory allocations can throw out of memory errors that will crash the app
That is not an “inconsistency”. Crashing the application when you run out of memory is honestly in almost all cases the correct call and crashing is memory safe. Most applications can do absolutely nothing when running out of memory. “Handling” OOM is extremely complicated and most applications simply cannot handle it in any way.
Of course low level stuff needs to sometimes actually handle this, but it’s mostly an operating system thing. And Rust still allows you that control, it’s just not the default behavior of the collections and such in the standard library, because again, it almost never makes sense to try to handle OOM. But if you really need that behavior, you can have it.
You can trivially use C libraries in Rust, or any system language that supports the C ABI for that matter, and this includes many hobbyist languages. Zig is not special.
No Zig definitely is special. You don’t have to do any extra busy work to call C code - you can pretty much just #include the header and that’s that. It’s similar to calling C from C++.
In any other languages - including Rust - you have to do some work declaring functions, wrapping them and so on. It’s not hard but it definitely is a non-zero amount of tedious work (especially before AI). There’s absolutely no way you could describe it as “trivial”, unless someone else has already done that work for you.
But I don’t think it is a significant Zig advantage really. When I’m writing Rust, it’s extremely rare that I want to call any C code that someone else hasn’t already done the tedious wrapping for.
zig is a bit special in this regard though as it is a c compiler not just using ffi. this means you could swap out gcc, make autotools etc and drop in zig with a build.zig. mostly useful if you want to migrate large code bases as you can incrementally port the parts you want.
if you’re picking it up for a new project then yeah this probably doesn’t impact you much.
Beyond what amounts to a packaging difference, what does that even mean?
How do you think zero-cost C ABI support (including fully working cross-lang LTO) works in lang implementations that have that? And how do you think that’s different from what Zig gives you?
Note: “Zero-cost” means zero runtime cost, not zero compile cost. The compiler does real work — monomorphization and inlining — to make abstractions disappear, and that work shows up as longer build times. See Reducing Compile Time for the trade-off.
most of the benefits come from a shared code base, one compiler (which is insanely fast with incremental rebuilds and can watch files for changes) means changes in the c code reflect in a single build step within seconds. the benefit is primarily for the developer as the compiler output should be relatively similar.
Arguably Zig has a simpler approach to memory management (which can also lead to more errors, arguably) which makes the transition from
C somewhat easier. Downside is that the language is still under heavy development and you definitely have to be up for the ride.
Agreed that it makes the transition from C easier, but I’d also say it makes the transition from C more pointless. I don’t really know that much about Zig but from what I’ve heard, I don’t really get the benefits - if you want a fast systems-level language without guard rails, why aren’t you just writing C (or C++, if that’s your thing)?
Zig is way better than C in many other respects, so if you want a modern sane language and you’re either a Rust luddite or working on a project where memory safety isn’t that important, it might be attractive.
Like, if the choice is C or Zig, then Zig is pretty much a no-brainer (or it will be when it hits 1.0). It just fixes so many insane things about C that have been broken for literal decades.
working on a project where memory safety isn’t that important
I can’t really imagine anything where this is not the case, unless you’re doing like… I dunno, small scripts for personal use or something? But why would you use Zig or C or even Rust for that, just do Python or even bash at that point? Python is memory safe and perfectly suitable for very small programs where static analysis gives little benefit.
zig does have guard rails, they’re just different approaches. zig defaults to optional types where null must be handled. and memory safety is checked through unit testing and exposing debugger memory allocators that check for different memory corruption bugs.
rust takes a shift left approach where all declarations drive safety whereas zig takes a more laid back shift right where it’s expected you’ll have written tests. rust will force all developers to conform to produce good code where zig requires a bit more though, i mean every dev writes test cases right?
Saying that “memory safety is checked by tests” is basically saying “memory safety is not checked”. Yes, you can write tests. How do you know the tests cover all cases? How do you know the tests aren’t buggy?
Also, what about memory safety across threads? Are you testing multi-threaded scenarios? Are you ensuring you have no data races?
I also don’t understand how this is an argument for Zig over C. You can also test memory safety of your C code via various means, but it’s never a guarantee. Zig is the same. So again, it seems a bit more pointless to go from C to Zig. Going from C to Rust brings actual tangible guarantees of memory safety (outside of any unsafe usage, obviously).
in c code you will see malloc, alloc, free w/e scattered through the code base, most static tools lack because they don’t control the memory and just analyze address spaces or do static code analysis. they look top down and try to catch errors.
zig’s design forces you to create a memory allocator before any object initializations (alloc/free) and is typically constructed at the top level and passed through to functions. this allows you to swap implementation easily and use the allocator to claim memory or return an error to the caller if it can’t.
you can do some simple static allocator, general purpose allocator (can grow memory space as you allocate more objects) or in this case to test memory safety a debug allocator which you use in your tests. This moves the memory inspection inside of where your program allocates memory. this is more of an inside out approach where the analysis is produced by controlling the memory allocations and frees through a standard interface.
@SorteKanin@kewjo Fuzzing! Zig is working on an integrated fuzzer that will work seamlessly with the testing system.
And for those cases you don’t catch, there’s ReleaseSafe which have runtime checks to prevent illegal behavior.
Zig removes a lot of the footguns of C and also provides a lot of the tools you’ll need anyway built-in. The debug allocator does leak-checking. You have to unwrap your nulls. There is compile-time duck-typing so generic data structures don’t have to rely on void pointers. Also no separate preprocessor language.
I’m actually looking into learning zig. The deal is that I don’t really have an use case for it. My work vastly prioritizes development speed over actually fast programs
To learn rust, I just started writing all my personal projects in rust. I started with REST apis and basic CLIs.
Why are you considering Zig instead of Rust? Or is it in addition?
i like the way zig interfaces with c. even though it’s a “newer” (not 1.0) language you can import native c which means you have access to already really fast libraries. the build script and macros are the same language you write your code. the best part is you can interface with normal code (not unsafe) and can create boundaries where sure in the c side you can’t enforce memory safety, but where you interface you can convert into memory safe types.
to talk more about memory safety i think rust does a great job, however there are some inconsistentcies where a lot of memory allocations can throw out of memory errors that will crash the app whereas zig you could gracefully handle it. this is probably more important for lower level things like kernel than an app where not recovering means everything goes down.
honestly i wish there was an opt in borrow checker as some patterns are easily expressed, but honestly i would opt out for async code as it just gets verbosely over-declarative imo. also the new async in zig is really really cool.
That is not an “inconsistency”. Crashing the application when you run out of memory is honestly in almost all cases the correct call and crashing is memory safe. Most applications can do absolutely nothing when running out of memory. “Handling” OOM is extremely complicated and most applications simply cannot handle it in any way.
Of course low level stuff needs to sometimes actually handle this, but it’s mostly an operating system thing. And Rust still allows you that control, it’s just not the default behavior of the collections and such in the standard library, because again, it almost never makes sense to try to handle OOM. But if you really need that behavior, you can have it.
You can trivially use C libraries in Rust, or any system language that supports the C ABI for that matter, and this includes many hobbyist languages. Zig is not special.
No Zig definitely is special. You don’t have to do any extra busy work to call C code - you can pretty much just
#includethe header and that’s that. It’s similar to calling C from C++.In any other languages - including Rust - you have to do some work declaring functions, wrapping them and so on. It’s not hard but it definitely is a non-zero amount of tedious work (especially before AI). There’s absolutely no way you could describe it as “trivial”, unless someone else has already done that work for you.
But I don’t think it is a significant Zig advantage really. When I’m writing Rust, it’s extremely rare that I want to call any C code that someone else hasn’t already done the tedious wrapping for.
You know
bindgenexists, right?zig is a bit special in this regard though as it is a c compiler not just using ffi. this means you could swap out gcc, make autotools etc and drop in zig with a build.zig. mostly useful if you want to migrate large code bases as you can incrementally port the parts you want.
if you’re picking it up for a new project then yeah this probably doesn’t impact you much.
Beyond what amounts to a packaging difference, what does that even mean?
How do you think zero-cost C ABI support (including fully working cross-lang LTO) works in lang implementations that have that? And how do you think that’s different from what Zig gives you?
from rust docs:
most of the benefits come from a shared code base, one compiler (which is insanely fast with incremental rebuilds and can watch files for changes) means changes in the c code reflect in a single build step within seconds. the benefit is primarily for the developer as the compiler output should be relatively similar.
That has nothing to do with what we were talking about. And in any case:
Needs qualification vs. other languages for binaries with comparable runtime performance.
(Hint: you will be surprised.)
Not special or unique.
Not only not special, but literally exists in all workable build tools.
bindgen+build.rsis the Rust version of this.Arguably Zig has a simpler approach to memory management (which can also lead to more errors, arguably) which makes the transition from C somewhat easier. Downside is that the language is still under heavy development and you definitely have to be up for the ride.
Agreed that it makes the transition from C easier, but I’d also say it makes the transition from C more pointless. I don’t really know that much about Zig but from what I’ve heard, I don’t really get the benefits - if you want a fast systems-level language without guard rails, why aren’t you just writing C (or C++, if that’s your thing)?
Zig is way better than C in many other respects, so if you want a modern sane language and you’re either a Rust luddite or working on a project where memory safety isn’t that important, it might be attractive.
Like, if the choice is C or Zig, then Zig is pretty much a no-brainer (or it will be when it hits 1.0). It just fixes so many insane things about C that have been broken for literal decades.
I can’t really imagine anything where this is not the case, unless you’re doing like… I dunno, small scripts for personal use or something? But why would you use Zig or C or even Rust for that, just do Python or even bash at that point? Python is memory safe and perfectly suitable for very small programs where static analysis gives little benefit.
zig does have guard rails, they’re just different approaches. zig defaults to optional types where null must be handled. and memory safety is checked through unit testing and exposing debugger memory allocators that check for different memory corruption bugs.
rust takes a shift left approach where all declarations drive safety whereas zig takes a more laid back shift right where it’s expected you’ll have written tests. rust will force all developers to conform to produce good code where zig requires a bit more though, i mean every dev writes test cases right?
🤣 🤣🤣🤣🤣🤣
Saying that “memory safety is checked by tests” is basically saying “memory safety is not checked”. Yes, you can write tests. How do you know the tests cover all cases? How do you know the tests aren’t buggy?
Also, what about memory safety across threads? Are you testing multi-threaded scenarios? Are you ensuring you have no data races?
I also don’t understand how this is an argument for Zig over C. You can also test memory safety of your C code via various means, but it’s never a guarantee. Zig is the same. So again, it seems a bit more pointless to go from C to Zig. Going from C to Rust brings actual tangible guarantees of memory safety (outside of any
unsafeusage, obviously).in c code you will see malloc, alloc, free w/e scattered through the code base, most static tools lack because they don’t control the memory and just analyze address spaces or do static code analysis. they look top down and try to catch errors.
zig’s design forces you to create a memory allocator before any object initializations (alloc/free) and is typically constructed at the top level and passed through to functions. this allows you to swap implementation easily and use the allocator to claim memory or return an error to the caller if it can’t.
you can do some simple static allocator, general purpose allocator (can grow memory space as you allocate more objects) or in this case to test memory safety a debug allocator which you use in your tests. This moves the memory inspection inside of where your program allocates memory. this is more of an inside out approach where the analysis is produced by controlling the memory allocations and frees through a standard interface.
@SorteKanin @kewjo Fuzzing! Zig is working on an integrated fuzzer that will work seamlessly with the testing system.
And for those cases you don’t catch, there’s ReleaseSafe which have runtime checks to prevent illegal behavior.
Zig removes a lot of the footguns of C and also provides a lot of the tools you’ll need anyway built-in. The debug allocator does leak-checking. You have to unwrap your nulls. There is compile-time duck-typing so generic data structures don’t have to rely on void pointers. Also no separate preprocessor language.
To prevent some illegal behaviour. Again, I’m not an expert on Zig, but as far as I understand, even Release"Safe" is not actually memory safe.
Cooler name
But consider, Rust being named what it is led to the project name ffmpreg
Can’t argue with that
For great justice
Someone set up us the Rust?