[HN Gopher] Learning Zig
       ___________________________________________________________________
        
       Learning Zig
        
       Author : ingve
       Score  : 117 points
       Date   : 2023-09-09 15:28 UTC (7 hours ago)
        
 (HTM) web link (www.openmymind.net)
 (TXT) w3m dump (www.openmymind.net)
        
       | ukd1 wrote:
       | Nice post. I learnt via https://ziglings.org - koans where you
       | fix minor, and increasingly hard things to learn a languages
       | concepts.
        
         | satvikpendem wrote:
         | Rust also has something similar which is where I believe Zig
         | drew inspiration from as well: https://github.com/rust-
         | lang/rustlings
        
           | amj7e wrote:
           | Ok... I guess
        
       | Dwedit wrote:
       | Zig doesn't have any features integrated into the language to
       | make reference-counted objects painless to use. For that matter,
       | neither does C#.
        
         | throwaway17_17 wrote:
         | I would assume this stems from Zig's commitment to 'No Hidden
         | Control Flow'. By nature, syntactic sugar for reference
         | counting will involve the calling of functions inside the code
         | the sugar is standing in for. This would then require adding
         | the RC constructs as language primitives and hard code their
         | implementation into the language. As such, I don't think adding
         | RC and a 'painless' syntax to use it is likely to be a feature
         | Zig picks up or settles on for memory management in the
         | language.
         | 
         | This seems to be a hard line for Andrew, I don't think he is
         | unable to consider adding primitives to Zig, but the sense I
         | get from his recorded presentations is that the primitive
         | collection in Zig currently is very unlikely to expand as Zig
         | moves to 1.0.
         | 
         | NOTE -- I am not affiliated with Zig and don't know how the
         | process of language design works for them outside of A. Kelly's
         | being assumed to be BDFL and having final say.
        
       | satvikpendem wrote:
       | What are the pros and cons of Zig vs Rust? I see Zig mentioned
       | more and more here, especially with regards to threads about Bun,
       | the largest / most popular project in Zig currently, but I'm not
       | sure why I should use it over Rust. Zig seems like it still does
       | not solve the problem of memory safety, in that it has safety
       | issues that would be caught by a borrow checker or other such
       | memory safety checker [0]. You can still use after free, for
       | example:                   var hello = try allocator.dupe(u8,
       | "hello world");         allocator.free(hello);
       | std.debug.print("{s}\n", .{hello});
       | 
       | [0] https://www.scattered-thoughts.net/writing/how-safe-is-zig/
        
         | mamcx wrote:
         | Rust is what _most_ *should* use for system-level programming
         | and /or overall programming, if possible.
         | 
         | Rust is safer, better overall + ergonomics, ecosystem, etc.
         | 
         | However, Zig have some nice properties:
         | 
         | - Is easier to do bit/memory wrangling in Zig than in Rust
         | 
         | - Is FAR easier to cross-compile. To the point that for example
         | I use Zig to compile my Rust project for musl
         | 
         | - Is MUCH faster to compile
         | 
         | - Is far "smaller" that is nice in constrained situation (not
         | just "environments", for example, you can use zig for when you
         | will use gcc/llvm to compile some small c file)
         | 
         | Zig is a very good match if the scope of the project is
         | _relatively_ small. Rust shine much more when is more big or
         | you need to work for a team of people.
         | 
         | Also, if you plan to make a library that will be used by
         | others, better to use a safer lang.
         | 
         | I don't see both as competitors. They are excellent
         | complements, and my dream is to Zig to replace C and
         | Rust/ada/pascal to replace C/C++.
         | 
         | P.D: A probably good match is to make some low-level thing in
         | Zig (where before was C) and FFI it in Rust.
        
         | flohofwoe wrote:
         | In terms of safety, Zig is somewhere in the middle between C
         | and C++ on one side, and Rust on the other side (e.g. it
         | enforces much more correctness than C or C++, and has runtime
         | spatial, but not temporal memory safety (but it has a debug
         | allocator which doesn't recycle memory (or rather: address
         | ranges) and which should catch most temporal memory safety
         | problems - like your example).
         | 
         | Zig doesn't have separate sublanguages for macros and generics,
         | instead these are all handled with regular 'comptime' Zig
         | (along with type reflection).
         | 
         | Zig has builtin syntax sugar for dealing with optionals and
         | error unions, which makes code less noisy (although that may be
         | subjective - and I think Rust also got some of that over time).
         | 
         | Zig's interaction with the C world is excellent, and to a
         | lesser degree also to the C++ and ObjC world (the Zig compiler
         | can compile C++ and ObjC code, but still requires a C shim to
         | sit between Zig and C++ or ObjC code).
         | 
         | Zig has much less influence from high level functional
         | languages and less "type system wankery" compared to Rust, this
         | again is a good thing for some people, while disliked by
         | others.
         | 
         | A minor detail, but which I think demonstrates the Zig
         | philosophy: the Zig compiler executable is also the build
         | system and package manager. In Rust this is delegated to a
         | separate tool (cargo).
         | 
         | ...and my personal opinion: Zig is a lot more 'elegant' than
         | Rust which results in more joy when writing Zig code. Rust
         | feels entirely too much like 'designed by committee'. With Zig
         | I "grokked" the language in a weekend of tinkering, while with
         | Rust I never really had "fun" despite several attempts of
         | trying to like it.
         | 
         | TL;DR: If I had to create an absolutely waterproof and critical
         | isolated piece of code, I would probably write that in a
         | "simple Rust subset". For anything else I would definitely
         | prefer Zig.
        
           | throwawaymaths wrote:
           | Is memory safety the only thing holding you back? Suppose
           | there were a way to do static borrow checking, as a 3rd party
           | tool?
        
         | grayhatter wrote:
         | You shouldn't use it over rust... that's a nonsensical
         | question. That's like asking when you should use a hammer
         | instead of a screwdriver.
         | 
         | I use zig because it's enjoyable to use. I hate writing rust,
         | it feels like the language is actively fighting me. I started
         | writing zig, and started loving the process of simplify writing
         | code again. Zig is nice because, to steal their quote. I'm able
         | to spend my time debugging my code, and not debugging my
         | understanding of the language. I've stepped on a use after free
         | but because it's _so_ easy to write and use tests, I found it
         | and fixed it in tests.
         | 
         | Bugs are undesirable, but I can write just as many bugs in
         | rust. So I'm always so confused about why rust users are so
         | panicked about use after free, or other memory bugs. Like
         | somehow the only bugs rust has a handle on is the worst class
         | of bug? Such an odd idea I can't figure out...
        
           | throwaway17_17 wrote:
           | They typical argument given for the focus on memory related
           | bugs is that:
           | 
           | '{company,Github,bug/cve -tracker} says (following code
           | review | testing)* that 70% of reported bugs/exploits are due
           | to memory management failures.'
           | 
           | I write it thusly, because I don't actual know or remember
           | all the various permutations I've seen. But a few that I can
           | recall being mentioned would be Microsoft and Google,
           | regarding Windows and Chrome (or it could have been the
           | entire Google production code base). But other than these
           | types of statements I can't recall any support for focusing
           | on memory vs other error kinds. This line of argument has led
           | to developers who class memory 'unsafe' languages as
           | objective moral bads (and the development of such to be
           | inherently morally bad) [I was literally told this on HN, in
           | the furor over the announcement of Hare Lang]. I think it's
           | reactions like this that lead to your usage of the word
           | panicked, but I always try to assume the majority of
           | developers are just using a language they enjoy and getting
           | on with the business of making stuff.
           | 
           | Just as a parting note: I'm not attempting to disagree with
           | the statements by these companies, or with the general
           | premise that memory safety errors result in problems for
           | users of software. I'm slightly ambivalent to the whole
           | thing.
           | 
           | -- edit for spelling
        
             | wredue wrote:
             | I think your wording is off, because 70% of reports bugs
             | are not memory related.
             | 
             | I vaguely recall that 70% of *certain classes* of reported
             | security flaws were buffer misuses (which zig handles quite
             | nicely in releasesafe and using slices, which is
             | recommended)
             | 
             | Edit:
             | 
             | Found it:
             | 
             | 70% of security bugs were counted as safe buffer related.
             | Note that by sticking to slices and releaseSafe, zig
             | provides most of the same guarantees as rust in this arena.
             | 
             | It's unclear whether a buffer issue automatically
             | classified a bug as a security flaw as well, as in many
             | cases it's simply not. For example, a memory security flaw
             | was reported in Stockfish that was simply not a flaw.
             | 
             | We are also discussing the Microsoft OS, which is a whole
             | different beast than applications.
             | 
             | Overall, meh.
        
               | throwaway17_17 wrote:
               | I probably should have substituted 70% with (some
               | percentage big enough to attempt to draw conclusions).
               | But I think I got the 70% from so 'blank says 70% of
               | exploits in our codebase are memory related', but I could
               | be mis-remembering. I tried to make it as broad and
               | encompassing as I have seen the claim used in arguments
               | for memory-safety-centric programming.
        
             | tored wrote:
             | About 20 percent of all bugs in the Linux kernel are use-
             | after-free.
             | 
             | With that said, I think proper tooling can solve much of
             | the problems with unsafe memory languages. Question is
             | then, why doesn't it happen? Are developers uninformed,
             | arrogant or just lazy? Is forcing it into the language the
             | only way to solve this?
        
           | satvikpendem wrote:
           | Because I can either catch those bugs myself or let the
           | computer catch them for me. I'm lazy and a fan of letting the
           | computers do the work at compile-time so I don't have to run
           | into them at runtime, at 3 AM in production. It's not the
           | amount of bugs, I can also write out of bounds panic bugs,
           | it's the type of bugs.
           | 
           | And truth be told, if we get liquid types or dependent types
           | in Rust, even those runtime out of bounds checks would be
           | caught at compile-time too.
        
             | grayhatter wrote:
             | This argument doesn't make sense to me either, but maybe
             | I'm just stupid.
             | 
             | For something to die at 3am in production, that means
             | either someone pushed code way too late, or something
             | changed in the stack unpredictability. Your compiler
             | wouldn't have been able to predict either of those cases.
             | But bugs are bugs, if I'm called at 3am to fix a bug, I
             | don't want to spend hours trying to fight my compiler, and
             | then fall back asleep while I'm waiting for it to compile.
             | I want to quickly identify the issue, and then to be able
             | to write the smallest possible patch until morning. In my
             | limited experience, rust is conducive to neither of those
             | options.
             | 
             | And you said "if we get liquid types" I assume that means
             | you meant it to say if rust gets? Unless you meant to
             | identify as part of the rust language?
        
               | satvikpendem wrote:
               | My point is that the more bugs that are caught at
               | compile-time rather than runtime, the better, as it's a
               | much lower likelihood that something randomly breaks in
               | the middle of the night. It has nothing to do with when
               | someone pushed their code out or the stack changing.
               | Someone could have pushed a runtime bug that was not
               | caught (but that could have been caught at compile-time,
               | depending on the type of bug, of course) that then breaks
               | production later on when a specific thing gets triggered.
               | You wouldn't be fighting the compiler at 3 am as well as
               | the code because you likely wouldn't be fixing things at
               | 3 am in the first place, and if it's _not_ something that
               | 's caught at compile time, well then you'd be dealing
               | with the language either way.
               | 
               | Compile-time checks help you write better code, generally
               | speaking.
        
               | wredue wrote:
               | The idea that "compile time checks help you write better
               | code is unanimous and absolute" is simply false.
               | 
               | Rust itself demonstrates that compile time checks
               | sometimes result in worse code, as many people have found
               | especially when they need to do things rust doesn't like
               | for performance reasons.
               | 
               | For sure, some checks are unambiguously good. But there
               | is also definitely a moving target of a line towards
               | whether or not more checks has diminishing returns if not
               | negative returns on your code. That moving line will
               | depend on a lot of things.
               | 
               | You also need to be careful because "more checks" doesn't
               | mean "less work" as you've asserted. It means more work
               | in a lot of safe pointer scenarios in rust, and more work
               | actually does often translate to more logic bugs and more
               | complexity when anything changes.
               | 
               | As far as I can tell, more checks doesn't same any time,
               | it often just changes where your time is spent.
        
               | tored wrote:
               | Not a Rust developer, in what way is Rust forcing you to
               | write less performant code? Any good example?
        
               | Philpax wrote:
               | > For something to die at 3am in production, that means
               | either someone pushed code way too late, or something
               | changed in the stack unpredictability.
               | 
               | I don't think those are the only two scenarios. I think
               | the most likely scenario by far is user input triggering
               | a latent issue in a code path and promptly bringing the
               | application down. A classic example, of course, is a
               | missing bounds check.
               | 
               | Modern language design makes this less likely by
               | enforcing invariants, adding checks, and making these
               | kinds of issues impossible by construction. It doesn't
               | mean that there isn't a space for languages without these
               | safe guards, but it does mean you should have a _really_
               | good reason to use them.
               | 
               | > But bugs are bugs, if I'm called at 3am to fix a bug, I
               | don't want to spend hours trying to fight my compiler,
               | and then fall back asleep while I'm waiting for it to
               | compile. I want to quickly identify the issue, and then
               | to be able to write the smallest possible patch until
               | morning. In my limited experience, rust is conducive to
               | neither of those options.
               | 
               | In my experience with Rust specifically, I've actually
               | found it easier to make those kinds of fixes as the area
               | of code I have to reason about is much smaller. I don't
               | have to worry that a local change will have global
               | effects, as I can much more clearly see the dataflow.
               | It's not a silver bullet, but I've felt much more
               | comfortable doing emergency fixes on Rust than on C++.
        
         | eggy wrote:
         | For me, Zig is more of a better C plus. If I want memory safety
         | and high-integrity software at this point, I use SPARK2014, a
         | subset of Ada. It has a longer legacy for mission-critical
         | software than Rust. Adacore, a private company that provides
         | support for Ada and SPARK, are collaborating with Ferrous
         | Systems to bring all the goodness to Rust, but Rust does not
         | have the legacy applications or all the goodies (yet).
        
         | boberoni wrote:
         | "Why Zig When There is Already C++, D, and Rust?"
         | 
         | https://ziglang.org/learn/why_zig_rust_d_cpp/
        
         | scythe wrote:
         | Zig is trying to be a new C. Rust is trying to be a low-level
         | ML. Sometimes people say that "Rust is trying to be the new
         | C++" but this is only true in a more abstract sense that looks
         | at use cases -- it doesn't follow the same technical path C++
         | did.
         | 
         | You could probably make a reasonable analogy that
         | Zig:Rust::Go:OCaml but this isn't perfect. Zig is simpler to
         | work with but it doesn't have as many powerful features, like
         | certain Rust safety guarantees, as you mentioned.
        
           | satvikpendem wrote:
           | > _Rust is trying to be a low-level ML_
           | 
           | Yep, this is probably why I like it so much. I liked OCaml
           | when I used it and Rust derives a lot of features from OCaml,
           | as well as its initial compiler being written in OCaml, so I
           | think the creators saw how well parts of OCaml fit together
           | (Option and Result types, ADTs, etc) and added it to Rust, as
           | Rust was much different than currently [0].
           | 
           | [0] http://venge.net/graydon/talks/intro-talk-2.pdf
        
           | wredue wrote:
           | >doesn't have as many powerful features
           | 
           | comptime is easily one of the most powerful language features
           | of any language in existence. Comptime gives you literally
           | everything you get from macros and generics without the
           | complexity of needing to know 3 separate Turing complete
           | languages to get it.
           | 
           | Zig doesn't need a horde of random highly complex differently
           | rule bounded features all complexily interacting with one
           | another because it has 1 easy to use feature that eliminates
           | those needs.
        
             | satvikpendem wrote:
             | Ah, if only Rust didn't drive away the person who was
             | working on the comptime equivalent in Rust. Sadly, now it
             | is likely that that will be a long way off.
        
               | Ygg2 wrote:
               | If only 1% people whining about comptimes actually sat
               | down and looked into adding it, we'd have comptimes
               | already.
               | 
               | Disclaimer: I'm tentatively exploring this via macros.
        
             | veber-alex wrote:
             | > Comptime gives you literally everything you get from
             | macros and generics without the complexity of needing to
             | know 3 separate Turing complete languages to get it.
             | 
             | comptime doesn't allow you to create domain specific macros
             | like html! in Rust, it also doesn't allow you to constrain
             | what types are accepted by your functions. It also has its
             | own problems with long compile times.
        
               | dundarious wrote:
               | > it also doesn't allow you to constrain what types are
               | accepted by your functions.
               | 
               | It does, if by constrain you mean "succeed or fail": just
               | write a comptime if statement and @compileError. If you
               | mean a mechanism like concepts or SFINAE then you are
               | correct.
        
               | Laremere wrote:
               | > comptime doesn't allow you to create domain specific
               | macros
               | 
               | Sure it does!
               | 
               | Zig's string format function is written using comptime.
               | It parses the format string and validates the arguments
               | at compile time. See https://github.com/ziglang/zig/blob/
               | master/lib/std/fmt.zig
               | 
               | I also toyed around with turning a math equation dsl into
               | compiled statements at https://github.com/Laremere/alg I
               | got matrix math working so, eg, if you multiply a 2by1
               | matrix by a 1by2 matrix, it returns a matrix which is
               | typed to 2x2.
        
               | wredue wrote:
               | The concept of "interfaces" in zig is a comptime pattern
               | rather than a language construct. See
               | std.io.SeekableStream.
               | 
               | To check that an anytype meets the decls of
               | SeekableStream is rudimentary.
               | 
               | It's funny that you say that about html, as a project in
               | the discord was just released to get comptime html only
               | in the last few weeks. I don't remember the project name
               | unfortunately.
        
         | dijit wrote:
         | Rust is "a better C++" (for lack of a cleaner allegory).
         | 
         | Zig is "a better C".
         | 
         | Understanding that makes it clear where Zig shines and Rust is
         | less ergonomic.
         | 
         | Both are good, but I see them as complementary and not really
         | adversarial or in competition.
        
       | BaculumMeumEst wrote:
       | Does anyone know why Zig isn't up to date on homebrew (v10.1,
       | while v11 is latest)? I tried pulling a very simple SDL2 project
       | off github and building it on my macbook M1 and hit
       | https://github.com/ziglang/zig/issues/12069.
       | 
       | Homebrew also has no option for --HEAD, so I don't know if I'm
       | running into a fixed issue or what. If anyone has recommendations
       | or an example scaffold that shows how I can build a SDL2 zig
       | project on a M1 with SDL2 installed via homebrew that would be
       | helpful.
       | 
       | I can't get Rust-SDL2 to work on my system either, so maybe I'm
       | just forever cursed to use C++. At least I understand how to
       | interface with system libraries without playing build system
       | Jenga I guess.
       | 
       | Edit: I manually installed a later version. I tried a few small
       | SDL2 projects, but trying to run them all gave me:
       | 
       | ```error: no field or member function named
       | 'standardReleaseOptions' in 'Build' const mode =
       | b.standardReleaseOptions();```
       | 
       | Perhaps the build system had some breaking changes at some point.
       | I would need to figure out how the old build system worked, as
       | well as what changed, in order get past it.
       | 
       | OTOH ChatGPT was able to get me past my Rust issue (I gave it the
       | output of sdl2_config and it spat out some environment variables
       | to add to my ~/.profile which fixed my issue), so I will come
       | back to Zig when it's a little more stable
        
         | kristoff_it wrote:
         | Just download Zig from https://ziglang.org/download/. Manually
         | editing your path seems a better alternative than being cursed
         | to forever use C++.
        
           | flohofwoe wrote:
           | Btw, an official 'zigup' tool which can install multiple Zig
           | version side by side and switch between them would be a real
           | life saver, especially for switching between nightly and
           | stable. Having to find the right download link, unpacking and
           | setting up paths is a bit too 90's ;) (especially when trying
           | to keep up with nightlies).
           | 
           | This would also a great tool for easily setting up a Zig
           | toolchain on CI servers.
        
             | michaelsbradley wrote:
             | I tried out zvm (Zig Version Manger) on my Mac laptop
             | earlier today, seems to work even if it's not super
             | polished:
             | 
             | https://github.com/tristanisham/zvm
        
             | throwawaymaths wrote:
             | Since zig has clean projects, asdf isn't half bad with zig
             | (no idea if it does master)
        
         | wredue wrote:
         | I'd probably not use homebrew or macports for zig anyway,
         | because lots of projects track master (it's annoying when you
         | just want to write code. Good for people testing language
         | features in the real world usage and shutting them down if they
         | don't work out).
         | 
         | Anyway, I can't remember for the life of me if I added it, or
         | if it was there by default, but isn't ~/.local/bin in the path
         | by default on Mac? Download and drop the binary there.
        
         | BaculumMeumEst wrote:
         | I ended up doing a GitHub search on "SDL", with language
         | specified as "Zig", and sorted in reverse chronological order
         | and found https://github.com/Liam-Malone/ZigPong, which ran
         | without issues by running "zig build run" in the repository
         | directory.
        
       ___________________________________________________________________
       (page generated 2023-09-09 23:01 UTC)