Most active commenters
  • helen___keller(3)
  • j-james(3)

←back to thread

Zig is hard but worth it

(ratfactor.com)
401 points signa11 | 20 comments | | HN request time: 2.145s | source | bottom
1. rayiner ◴[] No.36150933[source]
Alternative languages are cool, but I struggle to see the point of a systems programming language that doesn't offer static memory safety in 2023. Rust isn't necessarily the best and final answer--it seems like there is a broad design space to explore for memory-safe systems programming languages. But Zig seems to occupy the same local maximum as C--a relatively simple, non-safe systems language--and doesn't have a killer feature that justifies not just using C.
replies(3): >>36151428 #>>36152916 #>>36155063 #
2. helen___keller ◴[] No.36151428[source]
If we’re comparing C to Zig I’m not sure what memory safety even needs to be mentioned for.

For C to Zig there’s plenty of reasons one might prefer Zig. For memory safety obviously you might opt to choose neither.

replies(2): >>36151840 #>>36160740 #
3. rayiner ◴[] No.36151840[source]
In a vacuum, one might prefer Zig. But given that everyone already knows C and the ecosystem is so highly developed, it takes a gamechanging feature like Rust's memory safety to make an alternative language attractive (beyond a "this is cool" project--which I totally support).
replies(2): >>36152648 #>>36152940 #
4. helen___keller ◴[] No.36152648{3}[source]
That is probably why Zig has such a focus on seamless C interop. There’s a good thread in these comments talking about this.

Regardless, point taken. You’re more or less describing the internal fear I have (mentioned in another thread) that if I dedicate time to a nontrivial Zig project I will regret it if/when there’s no Zig community in N years

5. haberman ◴[] No.36152916[source]
The killer feature of Zig IMO is comptime. C++ has spent over a decade now marching towards making more and more of the language available at compile time, but in an awkward and complicated way (constexpr, consteval, constinit). Zig comes out of the gate with a unified and coherent compile-time evaluation feature that effectively obsoletes not only constexpr/consteval/constinit, but C++ templates too. This is "doing more with less" in a way that I find really compelling.
replies(1): >>36154539 #
6. alwaysbeconsing ◴[] No.36152940{3}[source]
I haven't tried Zig, but "all the things you like about C plus better versions of most/all of the awkward bits" seems like a reasonable value proposition. Especially since the compiler can apparently let you use C painlessly alongside your Zig -- enabling incremental rewriting.
replies(1): >>36153323 #
7. j-james ◴[] No.36153323{4}[source]
Can you use Zig painlessly alongside C? Does `zig cc` or an equivalent provide for writing Zig libraries that then can be called by a main C function?
replies(2): >>36154394 #>>36154464 #
8. ◴[] No.36154394{5}[source]
9. helen___keller ◴[] No.36154464{5}[source]
Yes probably as painlessly as a nonC language can get. First class support for C calling conventions, struct layouts, and so on

https://ziglearn.org/chapter-4/ See here

replies(1): >>36156173 #
10. Conscat ◴[] No.36154539[source]
Zig does not have anything analogous to constinit, because Zig does not have object lifetimes or constructors. Comptime is also a massive pain to use for generating new data types (you have to return a type from a comptime function), and it cannot express anything analogous to CRTP.
replies(1): >>36159353 #
11. krupan ◴[] No.36155063[source]
Honest question here (that I have every time I see someone talk about memory safety in 2023), are you aware of Ada/Spark?
replies(1): >>36160731 #
12. j-james ◴[] No.36156173{6}[source]
Yeah, I read through that: unless I'm missing something I think what I'm curious about is "calling C code from Zig and vice versa" in the to-be-written section.

Nim also has support for `ctypes` and compiles to C as its main target: yet though its interop is powerful it lacks in ergonomics, formerly you had to manually wrap every function you wished to use and this was only recently fixed by a macro-heavy external library.

I'm wondering what Zig does because IMO even if you have an excellent technical solution getting people to actually use it alongside C is hard, it has to be seamlessly seamless. Nim's C interop is rarely used outside of wrappers and it even more rarely is used to produce C libraries (though perhaps that's more a fault of incompatible type systems)

replies(1): >>36156461 #
13. TUSF ◴[] No.36156461{7}[source]
With Zig, you just write something like:

  const c = @cImport({
      @cDefine("SOME_MACRO", "1");
      @cInclude("raylib.h");
  });
Which translates the header files directly into Zig and allows you to call into them under whatever namespace you assigned them under. You even get completions (assuming you're using the language server)
replies(1): >>36159904 #
14. haberman ◴[] No.36159353{3}[source]
I personally find returning a type from a comptime function to be quite elegant. Template parameters and regular parameters are unified into a single concept.

Zig's comptime is analogous to constinit, because it lets you compute a value at compile time and ensure that it is linker-initialized into the final binary image.

The point about CTRP is interesting, I'd have to think about that some more.

replies(1): >>36169935 #
15. j-james ◴[] No.36159904{8}[source]
Right, but I'm curious about the calling-Zig-from-C interop, not the other way around.
replies(1): >>36196814 #
16. Gigachad ◴[] No.36160731[source]
If Ada and Spark solve problems as well or better than Rust and have been around for longer, why have I never seen any program written in them?

I don’t know anything about ada/spark but it seems clear that something has gone terribly wrong for them to not have taken off like Rust has.

replies(1): >>36183051 #
17. Gigachad ◴[] No.36160740[source]
If you are going to leave C, why take a half step when you could go the full way and end up with the better tool.
18. Conscat ◴[] No.36169935{4}[source]
I would consider that similar to a `inline constexpr` variable rather than a `constinit` variable. A `constinit` variable calls a constexpr constructor, but doesn't produce a constant.

EDIT: Oh, I think I see how it's like `constinit`. If you have a non-`comptime` variable that is initialized by a `comptime` function, then it's a non-constant constant-initialized variable.

19. krupan ◴[] No.36183051{3}[source]
That doesn't answer my question.

To attempt to answer your question, you might be surprised to learn just how much Ada/spark exists in the world if you go looking. Most of it is not open source. I'm not sure they haven't "taken off like Rust has" because Rust is still very niche, kinda like Ada is

20. kmz42 ◴[] No.36196814{9}[source]
I was curious as well so I made a simple example to see how easy it is[0]

The documentation, especially for the build system, was lacking. But the interop itself is pretty smooth. Only rough point is that I can't define a struct type in Zig and use it in C; you HAVE to define your structs in C if you plan to pass them between the languages (as far as I know anyways).

Zig has documentation on making your Zig structs match the layout of C structs[1] so I assume the intended use case is not as I have done (use the C type in Zig) but instead of define a matching Zig type and cast your C structs into Zig structs, or vice versa, at the boundary between languages.

Structs aside, for functions you just stick "export" on the Zig functions to make them available at link time (presumably) and use "callconv(.C)" so C can call them cleanly. Very easy.

[0] https://github.com/kmz42/zig_c_interop_test

[1] https://ziglearn.org/chapter-4/#extern-structs