Comment by pron

5 years ago

Zig's main feature is what it doesn't have, and the languages you mentioned don't have that feature.

Other languages also have more-or-less general partial evaluation constructs, but they're not revolutionary because they didn't realise they can express traditional constructs in terms of partial evaluation. Zig is revolutionary in that its simple partial evaluation construct replaces generics/templates, typeclasses/concepts/traits, macros and conditional compilation. The result is something that is consistent, extremely powerful, and yet exceptionally simple.

Hacker news has a really hard time valuing simplicity. I think it’s an egotistical thing: I’m smart so I don’t need a simple language.

What people miss is that a simple a language allows you to apply your smarts to solving the actual problems in front of you instead of puzzling over language features. You can only handle so much cognitive load at once, and ideally the vast majority of that should be devoted to whatever problem you’re solving, not to the language itself.

Ironically, this fact is the same fact that makes complex languages more fun for hobbyists. There’s simply more to explore, and to try, and to solve, when your object isn’t building a product but instead playing with a language. It’s a different purpose, but people very rarely acknowledge this fact, likely because they’d rather pretend their purposes are clearly mechanical and business oriented. It’s ok to just want to have fun sometimes.

  • That's an interesting observation.

    It definitely has merit. I've run into this exact same thing in type-system heavy languages like Haskell/Scala/Rust, where I spend more time juggling abstractions than implementing features.

    But there is an additional dimension: abstractions often make the first implementation much more cumbersome. But most code is maintained and read much more than it is written, and abstractions can make extending and maintaining a code base much easier.

    It's also good to remember that the existence of certain language abstractions doesn't mean you have to use them.

    You have to find the right tradeoff.

    • Another point I disagree with the consensus about! Abstractions have their place, but a bad abstraction ends up spending more of its life getting torn down than it does productively simplifying the code. In my opinion each abstraction increases system cognitive load, and so they should only be added “lazily”, ie when empirical experience with the code proves that a particular abstraction would have broad and deep utility.

    • But simple languages don't mean more cumbersome abstraction -- take Scheme for example -- while C++ and Haskell's maintenance record isn't particularly great (Rust doesn't have one yet).

  • In all programming languages you must understand how the parser will understand and translate what you write, it sounds like Zig will always know your intentions and maximize your code, it sounds too good to be true

    • If Zig were a high-level language it wouldn't have been so impressive. There are plenty of simple high-level languages. But in low-level domains there is a lot of extra accidental complexity because you need to precisely define layout, control memory allocation and placement, and try to avoid, or at least control branches or dynamic dispatch. And you need to do all that in the worst-case, and you don't have a JIT. So far there have been two approaches -- C, which is linguistically simple but inexpressive and spectacularly unsafe, and C++/Ada/Rust, which is much safer and much more expressive but incredibly complex. Zig finds a new way, not through some magic, but through really exceptional and radical design.

      2 replies →

As mentioned in my other (wall of text) comment, that's not strictly beneficial.

It forces you to implement a lot of logic in "userspace" that other languages do for you automatically.

Complexity for certain abstractions moves from the language to user code, at the expense of consistency, cohesion, totality and (auto-generated) documentation.

It will be interesting to see how things play out for Zig once the ecosystem grows a little and libraries appear, but there are very significant downsides to this approach.

  • Which of those is more beneficial indeed remains to be seen and might end up being purely a matter of personal taste; the very thing you call a downside I see as an upside. I think that talking about the positives "consistency and cohesion" where composing primitives works as a positive is merely a matter of habit. Zig treats some aspects that other languages sees as primitives as if they were any other part of the language, where code and libraries rule rather than a growing collection of primitives. I do agree that in principle a language could be too unstructured for some domains (Lisp?) but interestingly, Zig didn't go as far as syntax macros, whereas Rust did. Anyway, Zig finds a surprising middle-ground that is, as yet, hard to definitively judge, whereas Rust, for better or worse, is more of the same.

    • I was thinking of The Lisp Curse[1] while reading your comment and then you mentioned the language! I’m quite excited by Zig (even if safety is lower priority for it than for Rust, it is really pushing the tooling envelope) but I do wonder whether the “anti-composition hypothesis” here holds up for relevant projects today. Many C programs include shims for compatibility between multiple different “library object models” (hell even strings count here) and they seem to be a common source of security and performance issues. Maybe in the domains where Zig is most competitive that dynamic won’t play out? Or maybe comptime provides tools that will still enable composition or at least allow for lower overhead “object model shims”? I suspect that it will be hard to know more about how it plays out until there is more language stability and code sharing, maybe even a repository like npm or crates.io.

      [1] http://www.winestockwebdesign.com/Essays/Lisp_Curse.html

      4 replies →

As the language evolve and people will want to do actual things with it, features will be added.

  • Assumption 1: people don't actually use Zig.

    Assumption 2: the more we do with a language, the bigger the language has to be.

    I am sceptical about (1), and the only way (2) can possibly be true is if the standard library is part of the language (which it really is not: it's user space stuff, curated approved by whoever's in charge). Don't be excessively pessimistic. It's just as irrational as misguided optimism.

    • In regards to assumption 1: zig's documentation isn't the greatest, and it's still pre 1.0 which may have turned many potential users away for the moment.

      I think the person you were replying to implies that after a certain point (1.0 release?), Zig's userbase will increase to such levels that it can be considered "used" by (many) people

      1 reply →

> Zig is revolutionary in that its simple partial evaluation construct replaces generics/templates, typeclasses/concepts/traits, macros and conditional compilation.

This is what C++98 did, except they called their one true comptime evaluation construct "templates", and they did it by accident. There's a reason why Rust introduced generics and typeclasses separately: C++98 templates as bespoke comptime evaluation was a disaster, and this was clear already in the C++ community.

  • > This is what C++98 did, except they called their one true comptime evaluation construct "templates", and they did it by accident.

    Right, except not at all, because templates' syntactic elements are distinct from the "object" part of the language, so it is not a partial evaluation construct for C++, but rather a separate (and rather complex) meta-language for C++. In Zig there is just Zig (with its superb error reporting mechanism), and comptime partially evaluates it. Zig distances itself from C++'s problematic design much more than Rust, which, when all is said and done, is pretty darn similar to C++.

    But that's the problem with revolutionary design. Your ability to compare it to what came before it is limited because it isn't really similar to anything. Luckily, Zig can be fully learned in a day or two, so there's no need to rely on comparisons for long. You can quickly learn it and decide if it's your cup of tea or not; even if it isn't, you'd have learned something quite refreshing and inspirational, and without spending too much time.

    I do agree that there is something more mysterious about Zig. Nobody knows how "good" Rust is yet, either, but it's probably no worse than C++ when we factor all elements that matter to C++/Rust developers, and we're willing to accept that it's also probably not drastically better, except maybe when it comes to undefined behaviour. Zig is more of an unknown because it is so different. It has the potential to be worse than C++, but it can also be much better. At the very least, it is very interesting in that it offers a completely new vision for how low-level programming could be done.

    • I really don't understand why someone would think Rust is "pretty darn similar to C++". I think about my code and data in Rust very differently to C++. C++ doesn't have tagged unions, Rust does. C++ does have inheritance, Rust doesn't. C++ templates are quite unlike Rust generics. Rust enforces safety and (mutable XOR shared), C++ doesn't. All of these lead to quite different design decisions for same-shaped problems.

      9 replies →