[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)