13 ms·
Why Zig When There Is Already CPP, D, and Rust? (2017)
- camdenlock 8y agoI have nothing against Zig, but... am I the only one feeling "new programming language fatigue" lately? Seems like there are several new ones per week these days.
- smt88 8y agoI get what you mean, but Zig is a little different because it's not a naive, vanity project. All of its motivations are practical and related to the usability of the language.
- isaachier 8y agoI usually agree, but at least Zig has something new to bring to the table (allocation safety).
- pjmlp 8y agoProgramming languages has been one of my major subjects at the university and I don't see anything new in Zig regarding memory allocation.
- AndyKelley 8y agoThe only thing that's new is the convention to actually handle out of memory correctly, and the convention to accept an allocator as a parameter rather than using a global allocator.
- pjmlp 8y agoYep, nothing new unless one only knows C.
- Caster9 8y agoIt's getting easier to build them.
- richardwhiuk 8y agoIt's not - it's getting harder to build worthwhile ones. The barrier to entry is higher, the expectations on the size of the standard library are higher, the expected quality of tools is higher.
- andrewflnr 8y agoBut it's getting easier to just implement a language at all. That might be all you need to hit HN. No one said anything about "worthwhile" ones.
- mmirate 8y agoThat says a lot more about HN than about anything else...
- andrewflnr 8y agoIt says that we look for more in an idea than pure utility, that cleverness and beauty also count. That's a good thing.
- mmirate 8y ago> That's a good thing. Maybe, maybe not, but luckily that question's not very important. Here's what is: Where is the cleverness and beauty in Yet Another Boring LLVM Frontend(tm)? Zig and Rust are more than that, I'll readily grant - but that description does fall under the umbrella of "implementing a language".
- blt 8y agoEverything in your second sentence is true, but it seems like LLVM has been a huge boost. I think a lot more programmers are comfortable with parsing and ASTs than they are with the x86 instruction set. Not having to write IL->CPU codegen or peephole optimizations significantly lowers barrier for entry to compiled PL development. (I say this as just an observer, having written interpreters but no compiled languages.)
- codr4 8y agoOne of my teachers at university kept repeating that you can't really call yourself a programmer before you've implemented at least one language. I don't know about that, everyone is entitled to an opinion. What I do know is that it's one of precious few things in software that I still find interesting enough to bother [0]. I'm guessing part of the answer is that this is where you end up sooner or later. And then we have the internet, which is a big part of the equation. It's easy to get numb, but I remember a time when information about implementing interpreters/compilers was VERY hard to come by. It's all good from my perspective, we're barely scratching the surface of what is possible and there are plenty of good ideas left to rediscover in our history. But I do wish that more designers would dare to step outside of the box more. Creating a language isn't about cherry picking features from existing languages, it's about finding better ways of solving problems. [0] https://github.com/codr4life/snabl https://github.com/codr4life/snabl
- pjmlp 8y agoAs language geek I love playing around with new languages. For production code I have learned to choose programming languages that are first class citzen in the platform or libraries that are required for a given project. While it might seem boring or outdated, it is much more productive and future proof than picking the language and then sort out how to integrate them.
- edflsafoiewq 8y agoWhat I like about Zig is that its comptime facility makes the compiler a mixed evaluator in Andrei Ershov's sense: the compiler works by, for comptime structures, evaluating them, and for non-comptime structures, emitting a residual program that will evaluate them at run-time. It offers an accessible form of partial evaluation.
- dixego 8y agoI love seeing new programming languages. Obviously one expects most of them will never get anywhere but it's interesting to see the ways in which people want to be able to make programs but are unable to in existing programming languages, expressed in the form of a language they'd want to use.
- lixtra 8y agoI still don't get why they provide a warn() to stderr but no print() to stdout. [1] [1] https://ziglang.org/documentation/master/#Hello-World https://ziglang.org/documentation/master/#Hello-World
- xyproto 8y agoIf you have a command line application, you probably either want to use a library that provides colors and more features, or output to file (where writing to stdout is more appropriate than "print"). When developing, "print" is more commonly used as an aid for the developer. Most "print" messages should either be removed or outsourced to a library when the program nears completion. "warn" fills a similar purpose as "print". If you really want "print", a small function that writes to stdout is quick to write.
- lixtra 8y agowarn() is just as complex to write as print(). One is included, the other isn't. If you classify all C-programs by what output they use (multiple counts allowed), printf/puts shows up with the highest percentage long before ncurses, X or anything else.
- AndyKelley 8y agoWhat's not included is an easy way to ignore errors when writing to stdout. If that's your complaint, then Zig is not the language for you. Zig also doesn't provide an easy way to ignore allocation failure errors, for example. Edge cases matter. There's no excuse for failing to handle errors.
- Phylter 8y agoIf I'm writing a command line application then, most of the time, I just want to let the user know what's going on. It doesn't always have to be fancy and I don't want to track down a third party library to tell the user all went well and give basic statistics. I'd go ballistic if I had to download a library to print out "35 records processed." It just doesn't make sense.
- comex 8y agoEschewing all hidden function calls is a reasonable design choice, but you give up a lot. No destructors means no smart pointers – and Zig doesn't seem to have a garbage collector, so I guess you need to free() things manually. No operator overloading means, among other things, no custom numeric-like types – including wrapper types for units (e.g. Feet) unless the language provides separate support for those (e.g. Go does, Zig seemingly doesn't).
- jetzzz 8y agoC++ and Rust need destructors because they both have unwinding and thus need to know how to destroy things. If there is no unwinding then calling destructors manually is not that bad if compiler checks that you do it. That said, I haven't used zig and don't know how it actually works.
- ioddly 8y agoI have yet to use Zig seriously, but I'm pretty sure "defer" is its solution to this problem: https://ziglang.org/documentation/master/#defer https://ziglang.org/documentation/master/#defer
- edflsafoiewq 8y agoI asked this in another thread, but how do generics work in the absence of destructors? Let's separate the idea of a destructor from the idea that a destructor is implicitly called at the end of a scope. In C++, if there weren't automatic destructor calls, you could still clean things up manually with a pseudo-destructor call, x.~T(), where T is the type of x. In C, there are no (user-defined) generics, so you always know the concrete type of x, so you know whether it needs to have a destructor called and what the name of that destructor is. In Zig, how would generic code create an instance of a generic type T that may or may not need to have a destructor called, ie. how do you know if you need to use defer and what the deferred expression should be? How would tooling be able to check that destructors were called if there is no special way of marking that a destructor exists?
- lixtra 8y agoThe article states > Zig has no macros and no metaprogramming but then in another place about zig[1]: > Compile-time reflection and compile-time code execution This does sound arbitrary more complex than macros (and is what actually got me interested in zig). [1] https://www.patreon.com/andrewrk https://www.patreon.com/andrewrk
- k__ 8y agoAFAIK Nim has the same, but they call it by its name, hehe
- AndyKelley 8y agoCan you link to Nim's userland implementation of printf? Here's zig: https://github.com/ziglang/zig/blob/822d4fa216ea8f598e4a9d53161800494f449a94/std/fmt/index.zig#L15 https://github.com/ziglang/zig/blob/822d4fa216ea8f598e4a9d53...
- simen 8y agoI don't think Nim has one in the standard library, but people have built variations on it. Here's a couple: * https://github.com/bluenote10/nim-stringinterpolation/blob/master/stringinterpolation.nim https://github.com/bluenote10/nim-stringinterpolation/blob/m... This one does string interpolation and a printf-like syntax with compile time type checking. It does call out to C but only after it's already parsed and validated and transformed the format string. * https://github.com/kaushalmodi/strfmt/blob/master/strfmt.nim https://github.com/kaushalmodi/strfmt/blob/master/strfmt.nim This one implements a more complex string formatting syntax with lots of convenience functions. It's more complex but provides a lot more functionality than the previous one without relying on FFI. I'm not a Nim programmer but I imagine those two demonstrate how Nim metaprogramming works even if neither exactly duplicates the behavior of printf.
- dom96 8y agoNim also has this in the stdlib now: https://nim-lang.org/docs/strformat.html https://nim-lang.org/docs/strformat.html
- wycy 8y agoFrom what I've seen so far, I really like the clean syntax of Zig. I want to like Rust, but it looks so verbose and loaded with special characters.
- steveklabnik 8y agoWhich special characters bother you the most? Before 1.0 we largely removed most of them.
- wycy 8y ago::, & (pass by ref?), ! (macros), {:?}, _ => (), whatever is happening in this example with <T> and [T]: fn largest<T>(list: &[T]) -> T { To be fair, some of these are in Zig too, such as &.
- gnud 8y agoI'm a rust newbie, but I have to disagree. Your "horror example" is actually very readable for most programmers familiar with either Java, C# or c++, I think. In java or C# it would be something like T largest<T>(T[] list) The major difference being the reference syntax in rust, but that's the price of explicit ownership/no GC. I love the fact that it's obvious where macros are being used. _, => and () are originally from ML, so I know it from my university days, but these days you also find some or all of them in C#, Java, Kotlin, ES6. So a lot of programmers have already been exposed to them.
- steveklabnik 8y agoYeah, I guess * :: is the same as in many other languages * & too * ! is unique, I guess * The format string stuff is based on ... C#/Python stuff? I forget exactly. * _ => () is composing three other bits of syntax that aren't unusual on their own * <> is genrics, like in many languages * [T] is slices, which are not entirely unique but are also similar to array stuff which uses []s Thanks for elaborating, it's helpful to understand the perspective.
- 8y ago
- jordigh 8y agoI'm just happy that D was mentioned. Yay, D! Also, D's metaprogramming is an utter joy, almost lisp-like, without the craziness of C++ templates. Give it a try! An intro to one ingredient of the magic of D metaprogramming, compile-time function evaluation: https://tour.dlang.org/tour/en/gems/compile-time-function-evaluation-ctfe https://tour.dlang.org/tour/en/gems/compile-time-function-ev... An example of the kind of introspection available in the D stdlib: https://wiki.dlang.org/Finding_all_Functions_in_a_Module https://wiki.dlang.org/Finding_all_Functions_in_a_Module This one's really cool, a library that lets you build an entire grammar of your choice and evaluate it at compile time: https://github.com/PhilippeSigaud/Pegged https://github.com/PhilippeSigaud/Pegged Nim's metaprogramming seems quite similar, and I sometimes wonder if perhaps it took some inspiration from D.
- nerdponx 8y agoNim appears to have taken a lot of inspiration from D in general, eg UFCS.
- VHRanger 8y agoI wish more languages had UFCS. It makes for really readable code.
- rattray 8y agoFor others unfamiliar with the acronym, it looks like it's Universal Function Call Syntax - en.m.wikipedia.org/wiki/Uniform_Function_Call_Syntax Lets you call top-level funtions as if they were metnks, with the receiver as the first argument. For example, these two are equivalent: add(x, y) x.add(y) As an aside, I added a similar feature to my compile-to-js lang (http://lightscript.org http://lightscript.org) and have found it to be a delightful feature. I hope an equivalent passes TC39.
- 542458 8y ago> compile-time function evaluation Sorry, potentially stupid question incoming: I thought this was pretty standard for c++ optimizing compilers. What makes D's version of this special?
- partycoder 8y agoThis is a tetris clone made in zig https://github.com/andrewrk/tetris https://github.com/andrewrk/tetris I bit hard to follow without the syntax highlighting, but seems a good example of what a larger application would look like.
- AndyKelley 8y agoHere's an even better example: https://github.com/Hejsil/pokemon-randomizer https://github.com/Hejsil/pokemon-randomizer Also here's a game: https://gitlab.com/dbandstra/oxid/ https://gitlab.com/dbandstra/oxid/
- WalterBright 8y ago"C++, Rust, and D have a large number of features and it can be distracting from the actual meaning of the application you are working on. One finds themselves debugging their knowledge of the programming language instead of debugging the application itself." It's an interesting point. My experience with it, though, is that if the language is too simple, the complexity gets pushed off into the application. The result is "boilerplate", a lot of code that gets routinely cut&pasted into applications. The thing about complexity in the language, on the other hand, is once you do learn the language, that skill follows you with every app you work with. With complexity pushed to the app, you have to re-learn it with every app. A screwdriver can do a lot of things - chisel, hammer, scraper, prybar, punch, paint stirrer, shim, etc. But I prefer having a set of tools designed to be chisels, hammers, etc. My projects come out a lot nicer.
- nerdponx 8y agoIt's an interesting point. My experience with it, though, is that if the language is too simple, the complexity gets pushed off into the application. The result is "boilerplate", a lot of code that gets routinely cut&pasted into applications. This is a frequent complaint I hear about Go: they made the language too simple in certain places. People also tend to cite Rich Hickey's distinction between "simple" and "easy". So the question about Zig becomes one of what exactly was kept simple, and what was allowed to become complex? I think the world would benefit from a Hyperpolyglot-style comparison here. Rosetta Code is too much of a mess; ideally, I want to see a thoughtful side by side comparison of the same program written in several languages, with commentary.
- weberc2 8y agoI think many Go developers would consider this a feature (I do, anyway). A little boilerplate is better than a complex language. I say this with a background in C++, Java, and Python. I’m a fair bit more productive in Go and my code tends to be of higher quality (less headspace devoted to language complexity and more room for application complexity).
- int_19h 8y agoZig might get away with it by restricting itself to a narrow niche where this kind of simplicity is advantageous. Go tries to eat a much larger piece of the pie, and the deficiency is felt more as a result.
- bitL 8y agoHeh, property keyword was my favorite in Delphi/C# and I really missed it in C++. So Zig is not for me.
- oconnor663 8y ago> There are some standard library features that provide and work with heap allocators, but those are optional standard library features, not built into the language itself. Note that this is also true of Rust. Programs build using `no_std` and `libcore` don't have an allocator. A surprising amount of functionality is still available, like sorting and string splitting.
- nicoburns 8y agoYes, but zig takes it a step further by allowing you to pass a heap allocator into the standard array/vector type. There are discussions about implementing something similar in Rust, but it doesn't exist yet...
- frutiger 8y agoC++17 allows that too with all the containers in the std::pmr namespace.
- aey 8y agoWhat I want in a systems language is heap allocations that are typed. A Monad basically to wrap the heap context.
- hartror 8y ago> C++, Rust, and D have a large number of features and it can be distracting from the actual meaning of the application you are working on. I've just started working in Rust and found it to have the right number of features compared to C++.