[HN Gopher] Looking at Zig Programming Language
___________________________________________________________________
Looking at Zig Programming Language
Author : ksec
Score : 122 points
Date : 2022-04-05 14:19 UTC (8 hours ago)
(HTM) web link (codecs.multimedia.cx)
(TXT) w3m dump (codecs.multimedia.cx)
| mc4ndr3 wrote:
| Zig's ticketing moderation staff are humorless, gatekeeping
| stiffs. No thanks.
| xtian wrote:
| Sorry- what?? Is the implication that you made a joke issue and
| are upset about how it was handled?
| Shadonototra wrote:
| You should take a look at D, if all you want is C/C++ like code,
| then you can focus on -betterC and use the libc or your own
| batteries (like i do)
|
| It is the perfect language, don't sleep on it!
| throw_m239339 wrote:
| D had its chance. It made the mistake of trying to be a paid
| language (like Rebol) and failed at it, because clearly unless
| you're target a niche but lucrative industry, languages with a
| paid compiler are mostly a failure in the era of GCC and co.
| It's too late to develop a significant community around D. Rust
| clearly got the community aspect right.
| Shadonototra wrote:
| Rust is a failure because it takes an eternity to build
| projects, and is now infected by NPM-hell dependency
| management
|
| Imagine you have to wait for hours for your tests to compile
| and then to run, and then your micro services to compile to
| deploy a security update for a major CVS
|
| Rust is poorly designed with poor syntax with a poor
| foundation that can't scale in today day and age
| the__alchemist wrote:
| I've been doing a lot of translating C to Rust lately, and
| the Rust variants are much cleaner and more explicit.
| Especially regarding namespaces (ie no need to
| name_space_name_every_data_structure), explicitly declaring
| array types and references of instead of using pointers,
| and state management.
| Shadonototra wrote:
| Everything 'RE'written in X, Y or Z will look better
| because the problem was already solved, you only have to
| rewrite the text
| tialaramex wrote:
| There's perhaps some tiny kernel of truth in this, but as
| a generalisation it's obviously horribly wrong.
|
| Imagine trying to rewrite GCC in Bourne shell, or trying
| to rewrite the Linux kernel as Java. The results are not
| going to "look better" they're going to be awful, these
| languages are a terrible fit for the problem.
|
| What people keep finding with Rust is that it's a really
| _nice_ language to write software you might otherwise
| write in C or C++. The defaults are correct, the tooling
| is great, the errors are superb, it 's just a very nice
| experience.
| audunw wrote:
| Zig and D comes at it from different ends. With D, it feels
| like the C replacement aspect of it is an afterthought, an add-
| on (I don't remember it being a big focus at all when I used
| it).
|
| Zig aims to be a C replacement from the start, including being
| a much better toolchain for cross-compiling C code than any
| other C compiler.
|
| For embedded development, which is what is relevant to me, I
| never found D a good option. If that has changed they need to
| work on the marketing.
|
| As an object-oriented garbage collected language with various
| nice features, I don't see what sets it significantly apart
| from C# anymore. Well, you can compile proper binaries. But
| dotnet core interpreters seems to be spreading on our Linux
| boxes, so then being able to run the same .exe in Linux and
| Windows is actually a nice thing. Then again I'm not in the
| market for such a language, so I probably shouldn't comment.
| Shadonototra wrote:
| Zig aims to be a total C replacement
|
| D is a natural evolution of C, fixes its issues (bounds
| checking and use after free for example), and adds some
| niceties that makes it pragmatic and polyvalent on top of a
| solid alternative to MACROs and metaprogramming capabilities
|
| You can do native system development, embedded development,
| high-level tasks thanks to the optional GC and it can also
| becomes a scripting language
|
| Something you can't have with Zig, but that's not its goal
| anyways
|
| Also D is one of the rare languages that maintains its own
| backend, its own compiler (with optimizations available!) and
| a community that grows organically without needing major
| corporations support, it is a true labor of love, and it
| still gets new features today (ImportC)
|
| Why i stick with D? because of all of the above! it's an
| unmatched language, that compiles code SUPER FAST!
|
| .. and the syntax remains similar to C/C++; no need to learn
| new syntax gymnastic
| jmull wrote:
| Eh, this is an entirely superficial take. (Pattern match: not
| just like the things I currently already know.)
|
| I don't think this has any value.
|
| (Not that there might not be valid criticisms of zig or insights
| into its value... But this article doesn't contain them.)
| ajkjk wrote:
| It all seemed like valid criticism to me. It wasn't at all
| pattern-matching to things they know, it was evaluating and
| critiquing in each in term, and preferring one or the other for
| various reasons.
| GeorgeTirebiter wrote:
| "No idea though where pointer dereferencing as foo.* = 42" I have
| no idea either, but it does remind me of BLISS; I remember there
| being BLISS-10 (for pdp-10) and BLISS-11 (for pdp-11), came out
| of CMU. (Apparently there were even more versions
| https://en.wikipedia.org/wiki/BLISS )
|
| All variables were pointers; and so a common BLISS statement
| would be:
|
| .Z = .X + .Y which in 'C' would of course be z = x + y
| gsliepen wrote:
| Interestingly, you can do foo.operator*() in C++:
| https://godbolt.org/z/f5Geqcvdj
| [deleted]
| nemo1618 wrote:
| I actually love the foo.* syntax. Think about it like this: if
| foo were a struct, then foo.x would give you the x field. But
| what if you want _all_ the fields? Then you 'd write foo.* -- a
| Unix glob!
| skywal_l wrote:
| TLDR: The author discuss its subjectivity towards the language.
| In short, they're not a fan of how zig handles errors, some loop
| constructs and the language design regarding keywords and built-
| in functions. They will not use the language even though it comes
| with interesting innovations.
|
| On the first two points, it's disappointing not to see a
| discussion on the goals of zig and why these choices were made
| [0]. Like any trade-off, there is a reason behind it.
|
| The third point, which occupies the biggest paragraph, is
| somewhat irrelevant to me.
|
| An interesting take but which remains at the surface. Might not
| be worth the 5 minutes it takes to read it.
|
| [0] https://ziglang.org/learn/overview/
| synergy20 wrote:
| why is this downvoted? I like the short description. I spent a
| few hours two weeks ago to walk through ziglang's tutorial(to
| see how fit it is to replace c/c++ for system programming), my
| summary so far is: interesting stuff, but not good enough for
| me to switch yet. Will be on my watch list for next few years.
|
| Did similar thing with rust(ziglang to c vs rust to c++),
| decided to stay with modern c++ but will keep an eye on rust as
| well.
| karmakaze wrote:
| This was my first assessment for my own use as well. Seems
| very much a 'kitchen sink' language that has everything, but
| nothing in particular that draws me to it. If I had pick out
| one differentiator it would be that the weird case/camel-
| insensitivity makes integrating convenient.
| aserafini wrote:
| What case/camel-insensitivity are you referring to?
| nrclark wrote:
| Are you possibly thinking of Nim instead of Zig here?
| AnIdiotOnTheNet wrote:
| As mentioned in a reply to your other post, Zig has no such
| feature except within number literals. `12345E04` is
| equivalent to `12_345e04`, but `identifierName` is wholly
| separate from `identifier_name`.
| verdagon wrote:
| I made a tiny roguelike game in Zig a few months back and was
| really impressed.
|
| One thing I really appreciate about the language is the emphasis
| on keeping things simple. I heard someone put it really well
| yesterday: when you're programming in Zig, you spend your time
| tackling the original problem, not tackling the language.
|
| Also, the article's complaints may be valid, but most of them are
| very superficial, which speaks to good language design, in my
| opinion.
| anoncow419 wrote:
| Do you have a public repository for said game you published?
| sk1pper wrote:
| Hmm, I didn't find that quite to be the case. I wrote a toy
| GPU-accelerated (using OpenGL via C) terminal emulator in Zig.
| My take is that I'll probably wait for at least a 1.0 before I
| start hacking my side projects in it again.
|
| My main issue was around finding good documentation and (not-
| outdated) examples, which I guess just comes with using a
| bleeding-edge language. The biggest thing I find lacking is a
| "Learn Zig" book that takes you through the whole language.
| Sure, https://ziglearn.org/ exists, but it needs about 10 more
| chapters. Zig types can get somewhat complex, especially when
| interfacing with C, for example - I remember some difficulty
| deciphering those. For many things I ended up just reading
| Zig's source code itself, especially when looking up standard
| library stuff.
|
| I mean I get it, who wants to write a book for a language whose
| features are unstable?
|
| On the plus side, I agree that I fought Zig a _lot_ less than
| when I first started learning Rust. And I still fight Rust if
| anything involving generics and/or nontrivial annotations is
| involved.
| loeg wrote:
| Seems to be getting hugged to death.
| https://web.archive.org/web/20220405142923/https://codecs.mu...
| roblabla wrote:
| Tiniest of nits to pick but:
|
| > and I wish rustc would have a stand-alone assembly files
| support
|
| Rustc now supports inline assembly and global assembly in Rust
| 1.59 (the very latest release). So this is now possible:
| /// Lib.rs file global_asm!(include_str!("asmfile.s"),
| options(raw));
|
| Which will cause asmfile.s to be assembled and included in the
| rust library.
| JoshTriplett wrote:
| Absolutely, and any time you can use the built-in asm support,
| I'd recommend using it.
|
| But also, I'd _love_ to see support for C and assembly files in
| rustc.
| wyldfire wrote:
| Note that a really common use case for assembly files (.S
| files) is to expect that the file be transformed with the C
| preprocessor.
|
| It would be interesting to imagine a replacement with a rust
| equivalent but I can't help thinking that it's difficult or
| impossible to come up with an architecture / exec format
| independent replacement. gas and cc1as support .macro
| directives - maybe that would suffice? But compatibility with
| existing assembly source files would suffer.
| Dork1234 wrote:
| Given the current political landscape Zig really needs to change
| there logo.
| speed_spread wrote:
| Nyet, other guys change logo. Zig not yielding. Zig strong.
|
| If start moving over anytime some fucker claims ownership of
| some symbol, you're gonna have a bad time. Much easier in the
| long term to stick to your guns (eh) and make it clear that you
| 1 - were there first and 2 - have nothing to do with those
| little suka
| anonymoushn wrote:
| Regarding error handling verbosity, you don't actually have to
| write _ = file.write(data) catch |err| {
| silence_err_somehow(err); ... }.
|
| You can just write _ = file.write(data) catch {
| ... }.
|
| And the first example of using `catch` in the docs[0] does this.
| It may be useful to also use the non-error return value of
| `write` though, because partial writes will return an amount of
| written bytes less than the amount you asked to write. You need
| `writeAll` if you want to ignore this concern, and then you don't
| have to write `_ = ` because the non-error part of the error
| union is void (so you don't have to use it). Then you get
| file.writeAll(data) catch { ... }
|
| [0]: https://ziglang.org/documentation/master/#catch
| nonsequitur wrote:
| Hint: It's `catch {}` instead of `catch { ... }`.
| anonymoushn wrote:
| That's right if you want to do nothing on error. I think TFA
| uses `...` to represent the code they would actually want to
| run if an error happened.
| wyldfire wrote:
| That makes sense. But it's easy to confuse a prose ellipsis
| with the C++ notation for indicating the wildcard exception
| acceptance pattern.
| kjs3 wrote:
| Zig is not C++.
| hibbelig wrote:
| May no programming language ever introduce "foo" or "bar"
| keywords, lest mayhem be upon us.
| wyldfire wrote:
| Sorry, I suppose you could infer that but it was not my
| intent. It was merely my suggestion that someone's new
| exposure to Zig might be 'tainted' by previous exposure
| to C++ syntax.
| karmakaze wrote:
| One 'catch' that makes me uncomfortable with Zig is the
| camel/underscore-insensitivity. How do you find all references
| of a method? Does your editor/IDE know how to find writeAll
| when I search for references of write_all? Do you have lint
| rules that are enforced for a project's source?
| AnIdiotOnTheNet wrote:
| Unless something has drastically changed since I last used
| Zig, it doesn't have the feature you're talking about except
| in the case of number literals. `write_all` is a completely
| different identifier from `writeAll`.
| lhorie wrote:
| That's nim[0], not zig
|
| [0] https://nim-lang.org/docs/manual.html#lexical-analysis-
| ident...
| nrclark wrote:
| Is is possible you're mixing up Zig and Nim?
| kristoff_it wrote:
| Well, if those are the biggest problems the author has with Zig,
| then we're doing a fine job :^)
|
| WRT having error unions just be a userland tagged union type,
| here's a reason why we don't do that:
| https://ziglang.org/documentation/master/#Error-Return-Trace...
| lhorie wrote:
| The error thing to me hints more at how people use errors in
| the wild than anything specifically about Zig per se. The
| example that comes to mind is propagating parsing errors from a
| recursive descent parser. Typically one just wants to unwind
| the stack with some user friendly string error message
| indicating what exactly went wrong, but philosophically
| speaking, a parse error isn't really exceptional, it's an
| expected code path for invalid input.
|
| The way zig seems to think about errors is that early returns
| via `try` shouldn't be leveraged as a control flow mechanism to
| bail and bubble up values across the call stack. I think rather
| than saying why the error handling is done the way it is, it'd
| be more valuable if there were documentation on how one is
| supposed to go about coding to be able to use this bail-to-
| bubble-up-values pattern. Currently, the workaround is indeed
| somewhat verbose as it requires mimicking the `try` mechanism
| (and/or using some sort of global error store or whatever).
| throwawayzig wrote:
| I think more importantly, the error return mechanism in zig
| creates a trace, and for parser early returns you don't want
| a trace, so a 'richer' struct union mechanism makes sense.
| anonymoushn wrote:
| I didn't really understand. What is the problem and what is
| the workaround? Can you give an example?
| defen wrote:
| The problem (which is a deliberate design decision) is that
| Zig's error unions, which have special built-in support at
| the syntax level, are just tagged unions with an integer
| payload. In other words, when you return an error (either
| implicitly via `try` or directly with `return
| error.MyError`), that error payload is just an integer
| indicating which error was returned. So to use OP's parser
| example, there's not a built-in way to attach some sort of
| diagnostic info to the error itself, the way you would
| with, for example, python exceptions. Using the built-in
| syntax, you can't do the equivalent of `raise
| ParserException(token, line_number)` and then unpack that
| error later in your code to display a nice error message.
|
| The workaround would be to store that info in some sort of
| global struct (which has all the usual drawbacks of global
| variables); add a context/diagnostics parameter to your
| function, or manually manage your own error union in
| userspace, which means you lose the nice `try` syntax.
| lhorie wrote:
| The problem is that in other languages, it's common to do
| this sort of idiom throw new
| Error("Expected foo, found bar at line " + line)
| // ...then elsewhere catch (e) { log("In
| file " + file + ":\n" + e.message); }
|
| In zig, you can't attach arbitrary strings to errors
| because errors are effectively enums (in the sense of that
| constant names map exclusively to ints). You can only do
| this `try callMe() catch return error.Something` (The
| `return error.Something` part is zig's "equivalent" to
| `throw error`, but notice how I can't tack on the error
| message string to the error)
|
| `try` only shortcircuits into the `catch return` expression
| for errors, but for cases like parsers you want to
| shortcircuit _and_ bubble up error messages simultaneously.
| You can kinda do weird workarounds by having a pointer to
| an error field in your input struct and mutating that prior
| to returning an error value, and /or doing weird nullable-
| to-sentinel-value-promotion shenanigans with idioms like
| `callMeMaybe() orelse return someSentinel("Expected foo")`
| to simulate the early-return-from-expression semantics from
| `try callMe() catch return error.Something`.
| Hoppetosse wrote:
| If you want to handle the error and also bubble it up,
| maybe even changing the what error bubbles up, you can
| just return an error from within the catch block after
| doing whatever handling you want. Either the captured
| error or something else.
|
| Specifically for recursive descent parsers, I pass around
| a reference to an regular struct that acts as an
| ErrorInfo object, and use that to pass diagnostic
| information up the stack. Control flow is still managed
| by the error returns, any additional info goes in the
| parameter.
|
| There is (was?) a proposal to add that capability to the
| language but Im not sure it had much traction.
| lhorie wrote:
| Yeah I think a lot of people have been settling for that
| pattern, but it's admittedly not ideal, in the same way
| that it's generally preferable to work with discrete
| values in a functional/pure fashion than shuffling values
| in and out of an out param list everywhere.
| samatman wrote:
| > _a parse error isn 't really exceptional_
|
| And a parse error should (I will argue) not be what Zig
| thinks of as an error.
|
| There are languages where try/catch became in effect the poor
| man's coroutine, and it's doubly confusing with parser
| "errors" because this is not something we need to handle as
| equivalent to an actual error in our program. A parser error
| is normal control flow.
|
| I would suggest that in Zig one might use suspend/resume to
| pass a parser error to something which prints an error,
| possibly returning with a 'fix' which lets parsing continue
| and maybe find more errors. https://ziglearn.org/chapter-5/
| zozbot234 wrote:
| Rust implements this at the library level via common crates
| like 'anyhow' and 'thiserror', on top of a tagged type and a
| standard "Error" trait. The latter was recently extended to
| allow for implementation of these features.
___________________________________________________________________
(page generated 2022-04-05 23:00 UTC)