[HN Gopher] Zig is hard but worth it ___________________________________________________________________ Zig is hard but worth it Author : signa11 Score : 329 points Date : 2023-06-01 10:44 UTC (12 hours ago) (HTM) web link (ratfactor.com) (TXT) w3m dump (ratfactor.com) | Alifatisk wrote: | May I ask what the hype is with Zig? What makes it so attractive? | | Is it the performance? The easy interop with C? The ease of | controlling the memory allocation? | cynicalsecurity wrote: | Wait, it's a real language? I thought it was a sarcastic article | about an imaginary language called zig making fun of hipster | languages desperately trying to replace C/C++. | nickelcitymario wrote: | > [...] easy things seem easy primarily because they are | familiar. Easy is subjective. But simple things are simple | because they do not complicate; they have fewer concepts. Simple | is objective. | | This should be printed out as a large poster in every office. | erichocean wrote: | Rich Hickey has done more to popularize that idea in recent | years than perhaps anyone else. [0] | | In a lot of ways, Zig is to the _systems programming_ space | what Clojure is to the _information processing_ space. | | If you have 5+ years experience, you want simple, not easy. | Both languages deliver real advances on that promise in their | respective domains. | | ---- | | Back to the article, perhaps not coincidentally, the product my | startup is developing is written primarily in Zig (language | runtime), Clojure, and an in-house Forth/Factor/Joy derivative | for user-level scripting. I guess I really do care about | simplicity... | | [0] Simple Made Easy: | https://www.youtube.com/watch?v=SxdOUGdseq4 | WhereIsTheTruth wrote: | The issues I have with Zig are similar to the ones I have with | Rust, the syntax.. I will never get used to it, I find it | tasteless and non-ergonomic | | But, I manage to set it aside because it provides enough | benefits, I mainly use Zig as a toolchain to crosscompile my | libraries.. and write some helper externs | | Hopefully they manage to improve and ease out the syntax by 1.0, | I have hopes | jadodev wrote: | Have any examples of syntax you find tasteless? Things in Zig | that feel ergonomic to me: comptime params > separate generic | args; ptr.* > *ptr; optional pointers > possibly null normal | pointers; separate syntax for slices, arrays, & pointers > 1 | syntax for ptr & arrays. | WhereIsTheTruth wrote: | var t: ?i32 = null; if (t) { t +=1; | } | | This for example doesn't work, you have to capture, many | little things like that that stacks up and ends up creating a | non-ergonomic syntax | | No for loop, so you have to do multilines things like, and | now you meet a new : construct, this pseudo for loop now | looks confusing to look at var i: i32 = 0; | while (i < 42) : (i+=1) { } | | Then constant casting between integers, and also floats.. | also no operator overload for the math types etc.. | | Also not a fan of the pointer difference between [] * [:0], | too much different nitpicking that makes iterating slow and | painful, I understand the benefits, but the way it's done is | not enjoyable, at least to me | | That's just whats on the top of my head, it's been a while I | haven't wrote Zig code so I may be remembering wrong | askkk wrote: | In new last version 0.10.1 it seems that for is not working with | two arguments? const std = @import("std"); | const expect = std.testing.expect; test "for basics" | { const items = [_]i32 {4,5,3,4,0}; var sum: i32 | = 0; for(items, 0.. ) |value,_| { sum += value; | } try expect(sum == 16); } ubuntu | 22.04, snap zig version 0.10.1 , zig test 1.zig produces: | 1.zig:7:12: error: expected ')', found ',' for(items, 0.. ) | |value,_| { ^ | | Edited: To update, I tried snap, but using snap install --classic | --beta zig is a security risk because it can change the system | and is not sandboxed. | EscapeFromNY wrote: | For loop syntax was changed since 0.10.1. | | Zig 0.10.1: for(items) |value| {} | for(items) |value, index| {} | | Zig 0.11-dev: for(items) |value| {} | for(items, 0..) |value, index| {} for(as, bs, cs, ds, | 0..) |a, b, c, d, index| {} | jeroenhd wrote: | I like Zig as a concept, but every time I've tried it, the | toolchain lacked good IDE and debugger support. I've tried some | plugins half a year ago but they either didn't work reliably or | they missed important features. I'm personally sticking with Rust | until the day comes that I can just add a VSCode/Clion plugin | that'll give me an interactive debugger with full autocomplete | support without fiddling around too much. | | There's a lot to like with Zig, despite its unconvential syntax | and some language decisions I personally disagree with. The | language is still in development but it's very promising and I'll | definitely try to learn it before it reaches that magical 1.0 | release. | jcalabro wrote: | I've definitely had a good experience writing Zig in VS Code | with the CodeLLDB extension on Linux [0] and the Microsoft C++ | [1] one on Windows. It's also got the Zig extension which comes | with the Zig language server [2]. | | [0] | https://marketplace.visualstudio.com/items?itemName=vadimcn.... | [1] https://marketplace.visualstudio.com/items?itemName=ms- | vscod... [2] | https://marketplace.visualstudio.com/items?itemName=ziglang.... | LispSporks22 wrote: | > Only time will tell if comptime is the "greatest thing since | sliced bread" or not. | | Common Lisp user here. Am I missing anything that Zig has in the | compile time department? | | edit: Also, does the code in the comptime block have to be valid | Zig? | kllrnohj wrote: | Personally I think comptime is a questionably design and is | something both Rust & C++ did much better. | | In C++ branches that don't have to "compile" are explicitly | marked as such with `if constexpr`. In Rust you've got macros | that are also explicit with required `!`. In Zig any branch can | be a ticking code rot time bomb, just like it was with C | #ifdefs. It's better in Zig in that it at least has to parse | and so you've got fewer blatant problems, but the category of | problems of "I flipped DEBUG from `false` to `true` and now I | have dozens of build errors to go fix" is still there. And you | really don't have any warning signs other than "this is | branching on something that _might_ be known at compile time " | | But honestly that's also my general impression of Zig as a | whole. It's very definitely a "better C", not something that's | necessarily good/competitive with the broader state of the | ecosystem. It's like a love letter to C, completely with many | of the same general problems that C is known to have and that | other languages have addressed. | kps wrote: | It only has to be syntactically valid (parseable). | cies wrote: | From the article: | | > Easy is subjective. But simple things are simple because they | do not complicate; they have fewer concepts. Simple is objective. | | I'd argue both are subjective, or with a better word: relative. | | I'd say Zig is easier and simpler than C in almost all regards. | The article does not specify what Zig is compared to in order to | make these statements. Probably the author had C in mind, but | that was not explicitly mentioned. | bakuninsbart wrote: | Where do you guys see good use cases for Zig? I'm intrigued by | the language but don't really have any good ideas on where to try | it out. | | I thought about trying it out in as small data engineering | project, but I'm not sure if language support is sufficient for | the kind of tooling I would need eg. Database adapters. | jgalt212 wrote: | I've been thinking about using it for Python hot paths. I'm not | smart enough to write rust (at least without limitless supplies | of aspirin). And I'd like to avoid C for all the obvious | reasons. | Dowwie wrote: | Try Elixir. | pjmlp wrote: | In what concerns userspace, I don't see any good case, if I | want a better C, without much features, I rather stick to Go | even if I dislike some of the design decisions. | | Or D, Nim, Swift, OCaml, Haskell, AOT C#, AOT Java,... | | If any kind of automatic memory isn't possible/allowed, I would | be reaching out for Rust, not a language that still allows for | use-after-free errors. | | Maybe it is a good language for those that would like to have | Modula-2 with a C like syntax, and metaprogramming | capabilities, and are ex-Objective-C developers. | distcs wrote: | > If any kind of automatic memory isn't possible/allowed, I | would be reaching out for Rust | | I have come to the same conclusion but then I also fear that | Rust will continue to expand in scope and become a monster | language like C++. Do you or anyone fear that? Is that a | possibility? | TwentyPosts wrote: | Will Rust keep growing? Yes, I think so. | | Will it turn into a C++-like monster? I don't know. Maybe, | but when it comes to C++ it always feels like its "monster" | status is largely a result of previous mistakes or early | design decisions piling up, and causing trouble (eg. | C-style arrays, exceptions, implicit conversions, fiddly | sum types rather than first class support, no pattern | matching etc.). | | Rust will grow large, and probably complicated, but the | real issue with C++ are all these past mistakes and a shaky | foundation, and Rust is doing much, much better in that | regard. Time will tell if we'll eventually look back some | of Rust's design decisions as bad or unwieldy (probably). | riceart wrote: | > Time will tell if we'll eventually look back some of | Rust's design decisions as bad or unwieldy (probably). | | I think time has already told for things like async and | lifetimes. | pjmlp wrote: | async, yeah it could be better, given the pains. However | note that adding async to .NET and C++ hasn't been a | panacea either, to the point that there is a prototype of | adding Go/Java green threading to .NET, done by the .NET | team. While with the C++ standard library there isn't an | executor runtime in the box. | | Lifetimes are painful, and a other languages are | exploring better ergonomics or combining automatic memory | management with affine/linear types, yet it was Rust's | adoption that pushed other language designers to actually | look into this. So from that point of view, quite a | success, even if Rust vanishes tomorrow. | TwentyPosts wrote: | Can't say much about async, since I really lack the | experience to say whether async in Rust could feasibly | and realistically be much better than it currently is. | Some people say that it'd be great if it worked as | effortlessly as in Go, but I assume that you don't get to | have that without performance tradeoffs. | | As for lifetimes, what's the issue? Do you have any | reason to believe lifetimes are frustrating because they | were badly designed, rather than the fact that they're | making complexity explicit which was previously hidden? | vilunov wrote: | Rust hasn't grown in scope very much since its release, but | in places where it has grown, particularly async and unpin, | I find that there features interact very badly with | lifetimes and borrowing. I am often forced to ditch | borrowing across async method calls and to put everything | in Arcs, even when the lifetime is well-defined and it | could be easily used if it had been scoped threads instead | of futures. I fear that newer features will be incompatible | with older ones in a similar way, but fortunately there are | no such features on the horizon. | | Considering all that, I still see Rust as the most sane | choice for writing native programs. I don't really want a | "better C", I want to write memory-safe software with | confidence, and that means static analysis or a thick safe | runtime, whatever is more suitable for the use case. | mr_00ff00 wrote: | Technically though, isn't memory safety not necessary in | some cases? | | For example, single player video games. You can exploit | your own machine if you want, but that's not an issue. | | I like rust, but if I ran into async issues and annoying | stuff, I could see a world where I grab a non-memory safe | language to make games easily. | nequo wrote: | Crashing the program during runtime and having to debug | it then is still a worse experience than knowing before | running it that it cannot crash (due to memory errors). | | This certainty comes at a cost, either by negotiating | with the Rust compiler or by putting up with a GC. But | depending on your calculus, that cost might be worth | paying. | yjftsjthsd-h wrote: | Memory safety isn't just a security thing, it's also a | reliability thing. That is, even if my games have zero | security sensitivity I'd still like them to not crash or | corrupt data. | pjmlp wrote: | It is an issue if it also allows players to work around | DLC and other goodies. | | Or if having the game on the system can be used by | another malicious application as jumping point into root | access, starting it as subprocess and injecting the | exploit. | | Example, Windows attacks via Notepad. | chjj wrote: | Do you maintain any C projects? Personally, I tried using zig | for its build system (which can also compile C and whose build | files are written in zig). One of the benefits of this was easy | cross-compilation to all major platforms. | | It might not be a _real_ use-case or anything, but writing a | `build.zig` file for an existing C project might be a good way | to at least dip your toe in the water. | mcdonje wrote: | >Use Zig as a zero-dependency, drop-in C/C++ compiler that | supports cross-compilation out-of-the-box. | | - ziglang.org homepage | ldelossa wrote: | I'm surprised that the reason I'm mostly interested in Zig is not | mentioned. | | This is C interop. | | I work with C quite a bit and I enjoy it, however writing a large | project in C can be tiresome. | | Having an option like Zig which can import C headers and call C | functions without bindings is pretty attractive, especially when | you want to write something a big larger but still stay in C | world. | ziml77 wrote: | The thing that's espcially nice about that interop is that Zig | includes its own C compiler. That eliminates the pain of having | a build script locate an installed C compiler and figure out | what options should be passed to it. | lost_tourist wrote: | Why would I use zig c compiler in place of gcc or clang? | Mainly for zig interactivity or does it have some advantage | other than that over the aforementioned compilers? | TUSF wrote: | Zig's C/C++ compiler is just clang, but with header files | for most major platforms included, and sane defaults, so | there's no hassle getting it it to cross-compile. Some | companies have been using Zig solely for an easier to use | clang. | lost_tourist wrote: | Ah I see, thanks for your answer! | workethics wrote: | Not only that, but zig makes linking against old glibc versions | easy. For example, to make an x86_64 linux build linked against | glibc 2.9 when using zig build all you have to do is pass: | -Dtarget=x86_64-linux-gnu.2.9 | GordonS wrote: | Damn, that's a magnificent feature! Maybe I should have | another look at Zig... | beefcafe wrote: | This is a killer feature for CTFs/OSCP/etc and why I started | using it. | Fiahil wrote: | C interop is not as much a "killer feature" as it used to be. | When you deal with data science, web and other similar domains, | reading and writing JSON ergonomically is much more important | than being able to call a C function directly. It's just a | nice-to-have. | afdbcreid wrote: | Yeah, but when you're doing systems programming (which Zig | aims at if I understand correctly), easy interop with C is | much more important than easy JSON marshalling. | billfruit wrote: | What about c++ interop? | Conscat wrote: | You can call internal and external linkage C++ functions from | Zig, but you can't do anything interesting like specialize | templates or evaluate constexpr functions. | esjeon wrote: | C-interop is pretty perfect for most usecases. The only trouble | I had was that, since command line arguments are converted to | slices in Zig, I have to convert them back to null-terminated | strings whenever I call C functions using any of the arguments. | Nothing difficult but slightly painful. | thih9 wrote: | > "I learned Zig in a weekend! ... Six hours! ... 6us!" say the | blissful lizards. | | I don't get it; is this a reference? Could someone explain? | tylerscott wrote: | IIRC the mascot is a lizard so here the comment is portraying a | Zig enthusiast keen on promoting the ease of learning Zig as a | lizard. That was my take. | codedokode wrote: | I don't know anything about Zig except that it is a low-level | language. Can someone please explain how it is better than Rust? | Decabytes wrote: | Zig is not my favorite language to program in, but I think it's | focusing on a lot of the right stuff. | | 1. Easy Build System 2. Drop in Replacement for c/c++ compiler | (zig cc) 3. Easy cross compliation 4. Single executable compiler | 5. Package manager 6. Debugabillity | | It's the sort of developer focus that has a huge impact | especially when you are doing it for more than just a hobby. | Crystal, another language I love, is weak in this area. No tree | sitter, No tier1 windows support, Major libraries like the Lucky | Framework that don't build on Windows, a buggy LSP etc. Don't get | me wrong I love the language, and I will continue to work in it, | and all of these things are in various states of progress, but | it's already at 1.8 and some of these issues haven't been ironed | out yet. I'm not just armchair complaining, I know these are | hard, and I will contribute once I am more familiar with the | language | jsheard wrote: | I get what Zig is going for in making all operations as explicit | as possible, but I fear that it's going to turn away fields like | graphics and game development where it _would_ be a good fit | except for the lack of operator overloading forcing you to go | back to C-style math function spaghetti. It 's all fun and games | until what should be a straightforward math expression turns into | 8 nested function calls. | audunw wrote: | I like Zigs justification for not having general purpose | operator overloading (no hidden function calls and loops) | | But I wish they added: | | 1. Ability to declare completely pure functions that have no | loops except those which can be evaluated at compile time. | Something with similar constraints as eBPF in other words. | These could be useful in many contexts. 2. Ability to | explicitly import overloaded operators, that can only be | implemented using these pure guaranteed-to-finish-in-a-fixed- | number-of-cycles functions. | | Then you'd get operator overloading that can be used to | implement any kind of mathematical function, but not all kinds | of crazy DSL-like stuff which is outside the scope of Zig (I | have nothing against that, I've done crazy stuff in Ruby | myself, but it's not suitable for Zig) | TwentyPosts wrote: | I am not much of a Zig-head, but the best compromise I can | think of is having a few operators which purely and solely | exist for this purpose. In other words, there is no operator | overloading, but you can define, say, "#+" for any two structs, | or something like that. | | So if you want to encode matrix multiplication, then you'll | always have to write `mat1 #* mat2`. This feels like a hack, | and isn't all that elegant, but it'd be clear that every usage | of such an operator is a disguised function call. (And | according to what Andrew Kelley said, it's all about not hiding | function calls or complex operations in seemingly innocent | 'overloaded' symbols.) | | If you want to take this one step further you'd probably have | to allow users to define infix functions, which would be its | own can of worms. | | Honestly, I am not particularly happy with any of these ideas, | but I can't think of anything better either! | ljlolel wrote: | Idea: allow some weird Unicode operators like Julia does. | Then it'll be clear the weird operator is doing something | weird and new. And this already works in other languages. | There are lots of Unicode | spenczar5 wrote: | Writing greek symbols is sufficiently annoying that I | always kind of resent code that does this. It's not just | about the first time you are writing code, but also when | you are reviewing it, or trying to share a snippet with a | coworker, or lots more scenarios. Maybe it's just me, but | writing 'z = x [?] d' is really tedious. | kps wrote: | [?] is near-worst-case since it's not even Greek. I think | domain-specific keyboard layouts are as much of a good | idea as language-specific layouts, but they're a nuisance | to install on *nix (trivial on OS X). Using .XCompose is | the most practical *nix approach, in the absence of | program-specific methods like Julia's tab-completable | backslash names. | Conscat wrote: | I interpret this as meaning that ibus is difficult to set | up. FWIW, Emacs and Kitty let you input unicode without | it. | lvass wrote: | Just use C-x 8 in Emacs and you'll get any symbol by | name, with autocomplete. | [deleted] | thechao wrote: | Maybe an operator-overloading _region_? #{ | m3 = m1 * m2 + m3; m3 += m4; } | | Basically, pure syntactic sugar to help the author express | _intent_ without having to add a bunch of line-chatter. | | Speaking of operator-overloading, I really wish C++ (anyone!) | had a `.` prefix for operator-overloading which basically | says "this is more arguments for the highest-precedence | operator in the current expression: a := b | * c .+ d; | | Which translates to: a := fma(b, c, d) | MH15 wrote: | Huh I've never seen this approach. Very interesting | solution, could be adapted to the JavaScript matrix | libraries I bet. | estebank wrote: | In Rust you could use a proc macro that parsed the block | and translates the token to a new token stream that uses | method calls with the appropriate operator precedence, | for arbitrary operations you could want to define. You're | effectively writing a compiler plugin and language | extension at that point. For targeted niche domains, this | might be worthwhile. | bakkoting wrote: | There's a not-very-active proposal to add operator | overloading to JS which takes a similar scoped approach: | | https://github.com/tc39/proposal-operator-overloading | thechao wrote: | This is how TeX handles math -- the "$" operator is an | "inline" version of the same. | renox wrote: | > I am not much of a Zig-head, but the best compromise I can | think of is having a few operators which purely and solely | exist for this purpose. In other words, there is no operator | overloading, but you can define, say, "#+" for any two | structs, or something like that. | | And those operators wouldn't have any precedence. | | > If you want to take this one step further you'd probably | have to allow users to define infix functions, which would be | its own can of worms. | | As long as these infix function are preceded by a | recognizable operator ("#" in your example), I think that | this would be fine. | flohofwoe wrote: | Zig has a builtin @Vector type that might come in handy for | most cases where in C++ a math library with operator | overloading would be used: | | https://www.godbolt.org/z/7zbxnncv6 | | ...maybe one day there will also be a @Matrix builtin. | jsheard wrote: | That still breaks if you layer any abstractions on top, for | example if you wanted to build an AoSoA packet of Vec3s you'd | have to define an addition of those in terms of a function. | | https://www.godbolt.org/z/v8Ta8hEbv | | Zig is exactly the kind of language where you'd _want_ to | build a performance-oriented primitive like that, but AFAICT | the language doesn 't let you do it ergonomically. | flohofwoe wrote: | That's true, but OTH that's already getting into territory | where operator overloading might start to become | detrimental because it hides important implementation | details which might not be expected from a simple '+'. | Conscat wrote: | It's a LOT worse than C++ SIMD libraries. | | In C++ (EVE, Vc, Highway, xsimd, stdlib), you can specify the | ABI of a vector, which allows you to make platform specific | optimizations in multifunctions. Or you can write vector code | of a lowest-common-denominator width (like 16 bytes, rather | than specifying the number of lanes), which runs the same on | NEON and SSE2. Or you can write SIMD that is automatically | natively optimized for just a single platform. These features | are available on every notable C++ SIMD library, and they're | basically indispensable for serious performance code. | throwawaymaths wrote: | Probably not. @Vector is not a mathematical vector, it's | SIMD. it makes sense because there are times when those live | in registers and a poly fill for stack memory isn't | burdensome. | | @Matrix makes less sense because when it gets big, where are | you getting memory from? | flohofwoe wrote: | For 'game-ey' math code, a matrix is at most 4x4 floats (64 | bytes), that's fine for a value type that might live on the | stack. | | vec2..4 and matching matrix types up to 4x4 is basically | also what's provided in GPU shading languages as primitive | types, and personally I would prefer such a set of "SIMD-y" | primitive types for Zig (maybe a bit more luxurious than | @Vector, e.g. with things like component swizzling syntax - | basically what this Clang extension offers: https://clang.l | lvm.org/docs/LanguageExtensions.html#vectors-...). | cmbothwell wrote: | You might like Odin, it has a similar philosophy to Zig | and supports swizzling: | | https://odin-lang.org/docs/overview/#swizzle-operations | | Matrix types are also built in: | | https://odin-lang.org/docs/overview/#matrix-type | | I've thought for a little while that Odin could be a | secret weapon for game dev and similar pieces of | software. | flohofwoe wrote: | I'm actually dabbling with Odin a bit in the scope of | language bindings for the sokol headers: | | https://github.com/floooh/sokol-odin | | It's a very enjoyable language! | pron wrote: | As someone who works on another language that is relatively | reluctant to add language features (Java) we regularly face | such dilemmas. A user shows up with a problem that could be | helped by the language. The problem is real and a language | feature would work, but there are many such problems, and | adding features to solve all of them will make the language | much bigger, overall causing greater harm (even those who don't | themselves use the feature need to learn it to be able to read | code). What we try to ascertain is how big of a problem it is, | how many programs or lines of code it affects, and is there | possibly a single feature that could solve multiple problems at | once. | | So I would ask you this: what portion of your program suffers | from a lack of user-defined infix operators and how big of a | problem is it overall? Even if it turns out that the problem is | worth fixing in the language, it often makes sense to wait some | years and then prioritise the various problems that have been | reported. Zig's simplicity and its no-overload (not just | operator overloads!) single-dispatch is among its greatest | features, and meant to be one of its greatest draws. | markisus wrote: | In robotics, numerical linear algebra expressions comprise a | large part of the code base. If not by line count, then | definitely by the amount of time spent writing, reading, and | debugging such code. This makes Zig unusable for these | applications, at least not without additional tooling. You | can get a feel for how unergonomic this is by avoiding the | use of all arithmetic operators in your code and instead | forcing yourself to use user defined plus(a,b), minus(a,b), | assign(a,b), etc, or programming directly with the C blas | api. | erichocean wrote: | > _You can get a feel for how unergonomic this is by | avoiding the use of all arithmetic operators in your code | and instead forcing yourself to use user defined plus(a,b), | minus(a,b), assign(a,b), etc, or programming directly with | the C blas api._ | | You've dramatically overstated your case, since that's true | of every Lisp-like language. | | Lisp is a perfectly suitable language for developing | mathematics in, see SICM [0] for details. | | If you want to see SICM in action, the Emmy Computer | Algebra System [1] [2] [3] [4] is a Clojure project that | ported SICM to both Clojure and Clerk notebooks (like | Jupyter notebooks, but better for programmers). | | [0] https://mitpress.mit.edu/9780262028967/structure-and- | interpr... | | [1] Emmy project: https://emmy.mentat.org/ | | [2] Emmy source code: https://github.com/mentat- | collective/emmy | | [3] Emmy implementation talk (2017): "Physics in Clojure" | https://www.youtube.com/watch?v=7PoajCqNKpg | | [4] Emmy notebooks talk (2023): "Emmy: Moldable Physics and | Lispy Microworlds": | https://www.youtube.com/watch?v=B9kqD8vBuwU | KerrAvon wrote: | Why do you think this is true of Lisps? Emmy would not | seem to be a good example because it actually does | overload arithmetic operators to support extended data | structures. Look at, for example: | | https://cljdoc.org/d/org.mentat/emmy/0.30.0/doc/data- | types/m... | erichocean wrote: | > _forcing yourself to use user defined plus(a,b), | minus(a,b), assign(a,b)_ | | This is the complaint I was responding to. Here is that | code in Clojure (a Lisp): // What the | GP claims is bad for doing math: plus(a,b) | minus(a,b) assign(a,b) // <= I have no idea what | this does, or has to do with math. // | Let's actually use the original math operators, but with | function notation: +(a,b) -(a,b) | // And here's the Clojure/Lisp syntax for the same: | (+ a b) (- a b) | | Lisp doesn't have "operators", so it doesn't have | "operator overloading." What it does have is multi- | dispatch, so yeah, the implementation of `+` can depend | on the (dynamic) types of both `a` and `b`. That's a good | thing, it means that the `+` and `-` tokens aren't hard- | coded to whatever the language designer decided they | should be in year 0, with whatever precedence and | evaluation rules they picked at the time. | | The point I'm making is that you absolutely DO NOT need | to have special-cased, infix math operators to "do math" | in a reasonable, readable way. SICP is proof, and Emmy is | a breeze to work with. And it turns out, there are a lot | of advantages in NOT hard-coding your infix operators and | precedence rules into the syntax of the language. | hellcow wrote: | Using plus(a,b) for complex types sounds fine to me... I | have to imagine if I were working with a huge file of these | for a while it would start to feel normal, just like every | language has a different syntax but you eventually feel | comfortable using. | KerrAvon wrote: | Are you sure you would find this more ergonomically | pleasing: | | assign(x, plus(a, plus(b, plus(c, b)))) | | When you could have: | | x = a + b + c + d; | | Or: | | (let x (+ a b c d)) | | ? | tuhats wrote: | I have played around with using @Vector for linear algebra. | | This removes the need for operator overloading for a vector | type, which covers most use cases of operator overloading and I | often in fact think is the only legitimate use case. | | I don't get to use `*` for matrix multiplication, but I have | found I do not mind using a function for this. | | I have only been playing with this in small toy programs that | don't to much serious linear algebra and I haven't looked at | the asm I am generating with this approach, but I have been | enjoying it so far! | bodge5000 wrote: | I'm no expert on zig, but the one area I have seen it shooting | up in popularity is game dev. Though I guess that is largely as | a replacement for C, so "C-style" wouldnt be much of a concern | jsheard wrote: | Zig looks like a fine C replacement, but C isn't what people | are using to make games in the vast majority of cases. It's | all C++, and operator overloading is part of the "sane | subset" that everyone uses even if they hate the excesses of | modern C++ as a whole. | felixgallo wrote: | as a long time game dev, I actively don't want operator | overloading. That's some spooky action at a distance | nonsense. I'm not sure I have seen a codebase that involved | operator overloading, either, and I've worked in or near a | good quantity of well-known titles. | jsheard wrote: | There's no accounting for taste, but the two major | publicly available engines (Unreal and Unity) both use | operator overloading in their standard math types. | Taywee wrote: | You'd rather use explicit function calls for all linear | algebra and geometry operations? I don't think adding two | vectors using an overloaded + is that spooky or distant. | flohofwoe wrote: | FWIW Zig can do that without operator overloading: | https://www.godbolt.org/z/7zbxnncv6 | cyber_kinetist wrote: | First of all that only works with vectors, but I want | operator overloading to also work on things like matrices | or custom types (for example quaterions, or a symmat3 | struct that represents a symmetric 3x3 matrix using only | 6 floats). | | Additionally, for efficient math code you often want | vector / matrix types in AOSOA fasion: for example | Vec3<Float8> to store an AVX lane for each X/Y/Z | component. I want vector/matrix operations to work on | SIMD lanes, not just for scalar types, and Zig currently | can't support math operators on these kinds of types. | felixgallo wrote: | I have a marvelous proof that you can solve that with | comptime but unfortunately the margins of this website | are too small to contain it. | lvass wrote: | Do us a pastebin, please. | kprotty wrote: | Vectors in Zig are SIMD types. Vectors in games are | probably algebraic types. Using SIMD for the latter may | not be that useful if 1) specific elements are accessed | frequently 2) transformations involve a different | operation happen on each element. | mr_00ff00 wrote: | Would love to see zig in game dev. I've tried some rust and | while I love rust in general, I find game dev in it a bit of | a mess. | adastra22 wrote: | Have you tried bevy? I'm starting with bevy for a non-game | project, but I'm blown away by how simple it is to use once | you get used to the magic. | the__alchemist wrote: | Bevy isn't on the same level as tools like UE and Godot. | adastra22 wrote: | Depends on what you're doing. I'm writing a non-game app | that requires a scenegraph, raycast mouse selection tool, | and other tools of the sort typically required by games | and provided by a game engine. But there's a lot of game | stuff I don't need, and I need to make major | customizations to the rendering engine. It ended up being | easier to implement in bevy, due to its modularity, than | it would have been in UE4 or Godot. | Ygg2 wrote: | To be fair Godot isn't on same level as UE. | mr_00ff00 wrote: | Maybe I need to give bevy a second go. My big issue is I | felt I was learning to speak "bevy" instead of using | rust. A lot of functions I wrote required queries of | components, but the queries were built and called behind | a magically wall. | | I don't have much game dev experience though outside of | simple games using libraries like raylib to just move and | draw stuff. Maybe once things get complicated enough they | are all like bevy. | adastra22 wrote: | This is true on both fronts, I think. Bevy magics away | the interface between you and the engine via the ECS | macros, in a way that is very unusual for a systems | programming language like Rust. But that's more or less | how all game engines are these days from what I | understand. | pjmlp wrote: | Not really, it is mostly around communities like Handmade, | most studios couldn't care less and it doesn't fit most | engines that they are using. | sigsev_251 wrote: | To be fair, there is an operator overloading proposal for | C2y/C3a and there is at least one compiler that offers operator | overloading as an extension. | kapperchino wrote: | For the math stuff you can do things like a builder pattern | where you can flatten the nested functions. But operator | overloading is definitely preferred | iskander wrote: | Is there anything akin to Maturin for Zig? | | I would love to use it as an extension language for Python. | helen___keller wrote: | My main issue with Zig is that I'm scared to invest time in | writing something nontrivial to see the community/adoption | flounder then regret not using Rust or C++ later | | The language itself is fun. The explicit-ness of choosing how | allocation is done feels novel, and comptime is a clean solution | for problems that are ugly in most languages. | | Aside from lack of community I'd say the biggest nuisance is | error handling in nearly everything including allocations. I get | that allocation can fail but the vast majority of programs I | write, I just want to panic on an allocation failure (granted | these aren't production programs...) | | Edit: in retrospect, allocator error handling verbosity is | probably necessary due to the power the language gives you in | choosing allocators. If I use the general purpose allocator then | my edge case is PC out of memory; if I use a fixed buffer | allocator, a failed allocation is a code bug or a common error | case, so we might want to handle the failed allocation and | recover | faitswulff wrote: | My impression of the Zig language as a total outsider is that | it seems like it has the underpinnings of success: it has a | niche, it has a governance model, and it has real commercial | users. It just has to not blunder very hard on the way to some | level of promised stability. | distcs wrote: | > If I use the general purpose allocator then my edge case is | PC out of memory | | What does PC mean in this context? | nativecoinc wrote: | Maybe "the whole computer is out of memory" (general purpose | allocator). Contrast with a custom allocator which might only | be able to work with a few kilobytes (for example). | helen___keller wrote: | Personal computer | kubanczyk wrote: | player character | loeg wrote: | > Aside from lack of community I'd say the biggest nuisance is | error handling in nearly everything including allocations. I | get that allocation can fail but the vast majority of programs | I write, I just want to panic on an allocation failure (granted | these aren't production programs...) | | The C strategy for this was just to wrap malloc() with | something called xmalloc or malloc_nofail or whatever: | void *malloc_nofail(...) { void *res = malloc(...); | if (res == NULL) { abort(); } return | res; } | | (Or whatever.) The same would work in Zig, I think. | helen___keller wrote: | Yes you can easily make a one liner allocation function in | zig that takes an allocator as input with a comptime type and | panics if allocation fails and returns the unwrapped | allocation | | I just say nuisance because zig code often looks like Go code | in that almost every return type becomes an error union as | allocation error handling (and maybe other errors) trickle up | TylerE wrote: | From my experience with Zig (limited but not zero) it seems | like an ok solution to a problem I don't have, and don't | forsee having. | bsder wrote: | > My main issue with Zig is that I'm scared to invest time in | writing something nontrivial to see the community/adoption | flounder then regret not using Rust or C++ later | | This is 100% a real concern. | | If I'm going to choose Zig, it's because it is _SO_ much better | on some axis that the community /adoption isn't an issue as I | gain the benefits almost immediately. That means that C++ and | Rust probably aren't in the scope of choice anyway. | | I especially like the comment from elsewhere in thread where | they are using it for scripting, of all things, because they | can pop out code that builds and works on Windows _and_ Linux. | That 's a good example--you gain the benefits immediately even | if you later have to unwind that to something like Python. | kuroguro wrote: | I suppose you could write a few line wrapper that panics :) | | But yeah, most of the time I don't even want to think which | allocator to use let alone handle it's errors. | eatonphil wrote: | This is basically what I've come to do in the Zig scripts I | write at work. | | It took a bit of getting used to when I joined but we agreed | as a team to have all meaningful scripts written in Zig not | bash (for one, bash doesn't work on Windows without WSL and | we need to support Windows builds/testing/etc.). | | It makes about as much sense as any other cross-platform | scripting option once I got used to it! | | Some examples: | | Docs generation: https://github.com/tigerbeetledb/tigerbeetle | /blob/main/src/c... | | Integration testing sample code: https://github.com/tigerbeet | ledb/tigerbeetle/blob/main/src/c... | | Running a command wrapped in a TigerBeetle server run: https: | //github.com/tigerbeetledb/tigerbeetle/blob/main/src/c... | rowls66 wrote: | I am truly puzzled by this. I understood Zig to be a very | low level language like 'C'. Why would you write scripts in | it? | eatonphil wrote: | It's significantly nicer to write than C (my opinion | obviously). I see it as a general purpose language. | | But mostly the team decided to do this because we wanted | to unify on one language and double down on the | investment in Zig. | | I'm not a fanboy (nothing wrong if anyone is, just | clarifying about myself); I think this choice was right. | 59nadir wrote: | For what it's worth I think this is an excellent choice. | Back in 2019 I was deciding whether I wanted to pursue | Zig full-time and one of the upsides that I determined | was that once you reach critical mass writing all of your | code for tools and things in Zig you end up with things | that are really exactly what you need and with a very | high baseline for speed, flexibility, and so on. | | Right now I'm considering the same thing but with Odin | and for many of the same reasons that I had for Zig; it's | an excellent language to write foundational code in and | once you do, you end up being able to build significantly | more understandable, reliable, stable and consistent | things. | | This, but on a company level, is a real multiplier. Once | you adopt a couple of Python scripts and that's OK, you | give up the possibility of wielding this sharp spear. | | Edit: | | I think "How I program C" by Eskil Steenberg is an | interesting window into what you can get if you laser | focus on a language and environment and allow yourself to | build up a mountain of code that you dogfood: | https://www.youtube.com/watch?v=443UNeGrFoM | | At some point I will likely soft-retire and at that point | it's exceedingly unlikely that I'll bother with using | other people's libraries except a few key ones that I | think are decent, and at that point there really is no | reason I'd sit down and write these fundamentals in | anything but a lower-level language. Odin, Zig or | something like it would pretty much be the only thing on | the table. | hoosieree wrote: | Binary executables are a nice feature, especially for | distributing to users. | | It's much easier for most people to download a standalone | "mac" or "windows" binary than to know if they already | have the right version of Python or Perl or Clang (and | all the transitive dependencies your project adds). | eatonphil wrote: | We don't host the built binaries of these scripts (we | could!), but we bootstrap the local environment through a | single bash script or batch script (Windows) that pulls | down the Zig compiler. Then everything else in the repo | depends only on that until we get until client-language | specific bits which of course depend on other languages. | | But yeah it is quite simple still. | vaughan wrote: | I'm moving all my scripting to TypeScript using Bun (JS | runtime written in Zig). | | For scripting its a way better choice. `bun:ffi` also | makes it trivial to run C or Zig code when you need to. | rowls66 wrote: | I guess I don't see C as programming language for writing | scripts in either. In my view any language that requires | a separate complication step is not a scripting language, | and therefore not a language in which one writes scripts. | In C or Zig you write programs. | | Maybe I am just being too pedantic. | eatonphil wrote: | I didn't call it a scripting language. Nor do I think C | would be great to write scripts in either. :) I only said | we write scripts in Zig. But if you'd like to call these | files programs instead of scripts then that's ok too! | chrsig wrote: | I think for the problem space zig is trying to fit in, it's | pretty essential to have custom allocator support thoroughly | baked in. | | It's the sort of thing that lets a data structure be used on | both a gpu and cpu, allocation out of shared memory, or | ensure that no dynamic allocations are happening at all. | | Most programs don't have those concerns - so zig may not be | the best choice for them. For the programs that do have those | concerns, forethought about allocators is pretty important. | Right tool for the job, and all that. | mgkimsal wrote: | https://archive.is/cMm11 | galaxyLogic wrote: | Love the picture. People often say how easy something was for | them. They are saying they are a very capable, smart person. | Would you rather hire someone for whom everything is easy, or | someone for whom things seem difficult? | | In other words saying they learned something fast or that | something is easy for them, is at least partially self-promotion. | So claims of how easy something was for them it have to be taken | with a grain of salt. | | The interesting thing for the rest of us is WHY something is | easy, or difficult. That would be helpful for others to know. | This article is just that, it tells us why Zig can be difficult. | What to look out for. | jksmith wrote: | Is this a writeup about Zig, or any Wirth language written 50 | years ago? Asking for some Modula2 OG. | latch wrote: | I've now written a lot of zig code (http.zig, websocket.zig, | log.zig, zuckdb.zig, etc.) I think Zig falls into an "easy to | learn, average/hard to master" category. | | Some insiders underestimate the effort required for newcomers to | build non-trivial things. I think this is because some of that | complexity has to do with things like poor documentation, | inconsistent stdlib, incompatible releases, slow release cycle, | lack of package manager, etc. For an insider living and breathing | Zig, not only aren't these huge challenges, they aren't really | "Zig" - they are just transient growing pains. For someone | getting started though, the current state of Zig is Zig. | | I wish Zig had a polished package manager (there's one in the | current development branch, but you don't as much use it as fight | it). They could then move some of the less polished code into | official experimental packages, helping to set expectations and | maybe focus the development efforts. | JC770 wrote: | I just start to learn Zig,any suggest to beginners?Bro | hiccuphippo wrote: | Other than the main documentation, check ziglearn.org and | ziglings.org. Also read the std code, specially the tests | when you want to know how to use something. | zoogeny wrote: | I've lately thought that a package manager is as essential to a | new language as a standard library. I would also add a LSP and | standard code formatter to that list. | | It is a bit unfortunate because all of the above is a pretty | tall order. We're getting to the point that new languages are | expected to boil the ocean by the time they reach 1.0 | chrsig wrote: | > I've lately thought that a package manager is as essential | to a new language as a standard library. I would also add a | LSP and standard code formatter to that list. | | Agreed. Especially on a formatter. The number of code review | comments it cuts out is incredibly time and energy saving. | | > It is a bit unfortunate because all of the above is a | pretty tall order. We're getting to the point that new | languages are expected to boil the ocean by the time they | reach 1.0 | | In order to get into production? yes. there are minimum | requirements that must be met. those are higher now than in | the past, because of lessons learned the hard way. those | problems have been solved (for some value of solved) in | existing ecosystems -- a new language wont change the need | for them to be solved. | | it shatters the dream of hacking up something on a weekend | and having it turn into a hit success, but it also removes | the case of hacking up something in 10 days and suffering the | consequences for the next 30 years. | | Until they have what you mentioned, the languages _aren 't_ | ready for large scale use -- they need to grow into it. They | can be useful prior to that -- enthusiasts and early adopters | can reap what benefits are provided. That adoption is what | fuels the development of things like a standard code | formatter. | | edit: fixed omission of a unit of time after '30' | 6keZbCECT2uB wrote: | Not sure about lsp, but I think if you defined your | language in tree sitter, you might be able to define a | basic autoformatter generically on tree sitter to | accelerate bootstrapping your language. | | You could also use an existing language agnostic package | manager like nix, guix, or conda to bootstrap your language | package manager. | | Lsp is something I don't know of a way to make that easy | without overly constraining the design space. | clessg wrote: | > but it also removes the case of hacking up something in | 10 days and suffering the consequences for the next 30 | years | | Ha, I thought this sounded distressingly familiar! | | "In September 1995, a Netscape programmer named Brandan | Eich developed a new scripting language in just 10 days. It | was originally named Mocha, but quickly became known as | LiveScript and, later, JavaScript." | savolai wrote: | Would love to understand better what exactly is language | specific about package managers? You would think a winner | would emerge in this space like one has in version control to | be used with all languages, just separate repos for different | ecosystems? | anon84873628 wrote: | I was also wondering this. Why does every language need to | reinvent the wheel? | vineyardmike wrote: | Different languages do imports differently. There are | different constructs for "exports" and modules and | namespaces that prevent a common single directory | structure. | | Pip used to store packages in a global location, now most | of python used a Virtual Environment per project. | | Node uses a "vendor" directory within the project | structure. This is probably the easiest case. | | Go used to store everything globally in the "go path" but | now with go modules it does something else. | | Java doesn't need source code, just single JAR files, but | it needs it within the classpath. | | C/++ is very flexible, but varied depending on how you | build and set up your project. | | Swift/ObjC requires doing whatever apple wants and dealing | with their tooling. | | Everything is different. If you want "one winner" the | closest you get it is the system package manager (of which | multiple exist) and pointing your project to its package | cache. But not all system package managers handle multiple | concurrent versions of the same package. | | Maybe one day people will standardize against Nix which | seems to be the closest? | arp242 wrote: | Zig has a pretty decent LSP. | | I'm not so sure a package manager is really all that | essential; it can certainly be convenient but especially in | the space Zig is looking at it's pretty workable without one | (without complex deep dependency trees you can use git | submodules or just copy a directory). Or let me put it this | way: I never really missed a package manager in Zig. | BaculumMeumEst wrote: | > I'm not so sure a package manager is really all that | essential | | I agree with you, but this is subjective. Not having a | package manager will probably turn off many from the | language. But it's OK for the Zig folks to make a call that | a lot of people won't agree with if it doesn't fit their | vision of the language. | ReleaseCandidat wrote: | > I'm not so sure a package manager is really all that | essential; | | For open source software (libraries or programs, that | depend on other libraries or programs), it is essential (if | you're not distributing single functions like with Unison). | For closed source it doesn't matter that much. | arp242 wrote: | "cp -r ~/some-lib ~/my-project/" works well enough if | some-lib doesn't have dependencies on its own. Or git | submodules if you want something a bit more fancy. I | sometimes do this even for languages with package | managers, as it avoids a world of complexity. | | Obviously a package manager is _useful_ , but Zig is | relatively low-level and long dependency chains are much | less common than in e.g. Python, Ruby, and of course | NodeJS. So I'd argue it's not _essential_. All the other | things mentioned in the to top comment are far bigger | issues IMO. | TylerE wrote: | [flagged] | tuckerpo wrote: | Why? A submodule can be frozen at a given commit. They're | trivially updated or rolled-back, too. | latchkey wrote: | > I've lately thought that a package manager is as essential | to a new language as a standard library. | | This was the approach Ceylon took. Sadly, despite a lot of | effort, the language never took off. | johnnyjeans wrote: | I disagree. I actively avoid languages that rely on package | managers simply because they only give the illusion of being | beneficial. It ends up being more boilerplate I have to learn | to use an ecosystem, because they don't actually solve | dependency hell and now there's a whole additional | complicated tool with its own DSL I have to contend with in | order to fix what's broken (or even diagnose issues.) | | The more peripheral crap I have to deal with to use your | language, the less I'm likely to use it in the first place. I | don't need, want or care to learn yet another idiosyncratic | fragile system. Finding source tarballs is a complete non- | issue, and inevitably I'm going to have to manually build | things anyways to figure out what erroneous assumption a | library is making about the underlying system which is | causing the build to fail or the runtime to crash, so the | package manager just ends up being extra steps. Without fail, | that has always been my experience with language package | managers. | | In the pursuit of making things simpler, we're really just | making them harder. | zoogeny wrote: | I'm not sure I understand this issue. The existence of a | standard package manager doesn't prevent you from manually | vendoring dependencies if you want to. I have personal | experience working on node.js projects where several | dependencies were just `cp` into a directory and treated | like local modules, no npm involved at all. | | It's like `apt` or `brew` for system dependency management. | It is there if you want it but you can just as well | download a tar and config/make/install yourself if you | want. | | In many ways, it is like a standard lib. No one forces you | to use it. If you prefer the simplicity of your own | implementations then I see no reason why you can't just | write your own. | | But when you want the advantages of a package manager, and | there are advantages that you may not appreciate but others | do, then having a standard one built into the language | feels preferable to having a dozen non-standard | independently competing variations that the community | cobbles together. | fauigerzigerk wrote: | The cynic in me would say that including a standard package | manager is absolutely necessary to stop several of them | popping up every year :) | gen220 wrote: | Just curious, not snide: what language fits this criteria? | | C/C++? Using Python 3.7+ in a way that completely ignores | Pip, because the stdlib is now quite expansive? | thegeekpirate wrote: | Odin | seba_dos1 wrote: | Python is quite often being used without pip, as the | modules are often packaged by distros already (and in | many distros they _have_ to be packaged this way in order | to include the application that uses them in the repos). | paulddraper wrote: | Must be C/C++. | JohnFen wrote: | I agree entirely. Relying on a package manager in order for | a language to be useful indicates to me that there's a | deficiency in the language. | pornel wrote: | Is every language supposed to come with HTTP and TLS | stack, clients for every database, de/serializers for | every format, every image and video codec, every | de/compressor, GUI toolkits, 3D rendering, Bluetooth... | where do you stop? | | And then how do you maintain all of this bloat to a | competitive level, so that users don't need to reach for | faster/newer alternative packages anyway? | | And how do you maintain portability and backward | compatibility of a language with such a vast API surface? | | In modern development there's just too much stuff to keep | everyone happy with batteries included. Sooner or later | users will need something that isn't built in, and that | will cause pain and crappy workarounds if the language | doesn't have first-class support for dependencies. | pdntspa wrote: | You could manage it like .net did before | chocolatey/winget -- pretty much a free-for-all, just add | yourself to the COM list through whatever means you want | and have at it | | But that was a mess. I still have nightmares from dealing | with windows assembly cache issues. | | Honestly it reminds me of some of the shit I've had to | deal with with pip (what do you mean you can't resolve | this dependency???) | JohnFen wrote: | I suppose that I just never had a problem maintaining any | dependencies in code I write. Package managers have long | been a bit of a pain for me as a developer, and with some | languages (like Python), they are a huge PITA for me as a | normal user of applications. | | So overall I don't view them in a very positive light. | They're something I have to put up with. | | No matter, it is what it is. Carry on. :) | pornel wrote: | When Python was originally designed disk space was | precious, and access to the Internet was rare, and its | dependency management was designed for that world. Its | multiple retrofitted package managers never fully fixed | it. | | However, better integrated package managers can work | well. In case of Node.js and Cargo, the main argument | against them is that it's _too easy_ to add dependencies. | jeroenhd wrote: | The problem with source tarballs is that you need to then | manually watch out for updates and bugfixes for every | dependency you pull in. You also need to deal with the | bespoke build system of your packages of choice or manually | build something compatible with your project. You can also | choose not to and skip vulnerable, buggy code for a few | years like some companies do, but that's hardly an | advantage. You also need to ship (and possibly license) all | of your dependencies. | | Alternatively, you can let the system package manager do | all the hard work for you. That works great, as long as you | only target one OS or put in the work to maintain | compatibility with multiple OS releases. | | My experience with languages without package managers is | that large, maintained projects all invent their own | package manager (remote git repos? shell scripts | downloading files? a two-stage build process written in the | language itself?) in combination with some sort of Makefile | generating hell script that breaks for a while when a new | OS release comes out. | | This approach works if you're the entire system. SerenityOS | can do this, because it's basically an entire operating | system and userland all inside one repository. ChromeOS can | probably do it as well, since the app portion isn't running | OS-native code anyway. For everyone else, it's just making | someone else do the work of the package manager manually. | paulddraper wrote: | > new languages are expected to boil the ocean by the time | they reach 1.0 | | The reason is that there are existing high-quality | languages/ecosystems. | | (Which is a good thing!) | adamrezich wrote: | package managers are relatively easy to put together and | release with your language--provided that you want your new | package manager and surrounding ecosystem to work exactly the | same as other, popular ones, without putting any effort into | improving the status quo. doing better than other languages' | package managers takes significant effort, because it's both | a computer engineering problem _and_ a social engineering | problem. | | it's nice when a new language has a package manager right out | of the gate, but I would like to see more new languages take | a more measured approach and aim to significantly _improve_ | upon past efforts, instead of merely replicating them out of | some sense of obligation. | cassepipe wrote: | To get an idea, what is your programming background ? Are you a | C or C++ programmer ? | VyseofArcadia wrote: | I used Zig for a weekend project and _loved_ it, but I am | resolved to not use it for anything else until it hits 1.0. I | don 't have time to write and re-write and re-re-write my code | as the language and stlib stabilize. | Tozen wrote: | If that's the thinking, looks like it will be a long wait. | Appears to be another 2 to 3 years before 1.0 hits. And it | publicly came out in 2016, so add all those years up. | TaupeRanger wrote: | Maybe a few years ago it would've been "worth it". But with LLMs | coming to swallow up all coding tasks and turning programmers | into prompt engineers within a few years time, I can't see it | being "worth it" any more. | mr_00ff00 wrote: | I don't want to make assumptions, but have you tried systems | programming with LLMs? | | A few years and everyone will be prompt engineers is laughable. | I hope I can actually use it productively for more than unit | tests in a few years. | Taywee wrote: | You still need to understand the code you are generating, | testing, and debugging. LLMs don't replace a need for more | expressive programming languages. | jiripospisil wrote: | I've been playing with it and so far but I'm more impressed with | their build system rather than the language itself (it seems to | be way more flexible and simpler than alternatives which is | pretty rare). They did however get the module system right. You | can just organize the file structure in any way you like. I hate | Rust's "everything is a single module" system with passion. | mike_hearn wrote: | How do you find it simpler? From taking a quick look it appears | to just be an API for invoking build steps, and the build | script is itself a Zig program. | | I ask if it's really simple, because the JVM space went in the | same direction with Gradle (build script = program) and by the | time it gets more sophisticated that can turn out to be pretty | painful. In particular, IDEs struggle to get the information | they need, scripts can become highly complex, and there are | various other problems. | pjmlp wrote: | Gradle is Ant reinvented, by those that didn't learn why we | moved into Maven. | rayiner wrote: | Alternative languages are cool, but I struggle to see the point | of a systems programming language that doesn't offer static | memory safety in 2023. Rust isn't necessarily the best and final | answer--it seems like there is a broad design space to explore | for memory-safe systems programming languages. But Zig seems to | occupy the same local maximum as C--a relatively simple, non-safe | systems language--and doesn't have a killer feature that | justifies not just using C. | haberman wrote: | The killer feature of Zig IMO is comptime. C++ has spent over a | decade now marching towards making more and more of the | language available at compile time, but in an awkward and | complicated way (constexpr, consteval, constinit). Zig comes | out of the gate with a unified and coherent compile-time | evaluation feature that effectively obsoletes not only | constexpr/consteval/constinit, but C++ templates too. This is | "doing more with less" in a way that I find really compelling. | Conscat wrote: | Zig does not have anything analogous to constinit, because | Zig does not have object lifetimes or constructors. Comptime | is also a massive pain to use for generating new data types | (you have to return a type from a comptime function), and it | cannot express anything analogous to CRTP. | helen___keller wrote: | If we're comparing C to Zig I'm not sure what memory safety | even needs to be mentioned for. | | For C to Zig there's plenty of reasons one might prefer Zig. | For memory safety obviously you might opt to choose neither. | rayiner wrote: | In a vacuum, one might prefer Zig. But given that everyone | already knows C and the ecosystem is so highly developed, it | takes a gamechanging feature like Rust's memory safety to | make an alternative language attractive (beyond a "this is | cool" project--which I totally support). | helen___keller wrote: | That is probably why Zig has such a focus on seamless C | interop. There's a good thread in these comments talking | about this. | | Regardless, point taken. You're more or less describing the | internal fear I have (mentioned in another thread) that if | I dedicate time to a nontrivial Zig project I will regret | it if/when there's no Zig community in N years | alwaysbeconsing wrote: | I haven't tried Zig, but "all the things you like about C | plus better versions of most/all of the awkward bits" seems | like a reasonable value proposition. Especially since the | compiler can apparently let you use C painlessly alongside | your Zig -- enabling incremental rewriting. | j-james wrote: | Can you use Zig painlessly alongside C? Does `zig cc` or | an equivalent provide for writing Zig libraries that then | can be called by a main C function? | [deleted] | helen___keller wrote: | Yes probably as painlessly as a nonC language can get. | First class support for C calling conventions, struct | layouts, and so on | | https://ziglearn.org/chapter-4/ See here | j-james wrote: | Yeah, I read through that: unless I'm missing something I | think what I'm curious about is "calling C code from Zig | and vice versa" in the to-be-written section. | | Nim also has support for `ctypes` and compiles to C as | its main target: yet though its interop is powerful it | lacks in ergonomics, formerly you had to manually wrap | every function you wished to use and this was only | recently fixed by a macro-heavy external library. | | I'm wondering what Zig does because IMO even if you have | an excellent technical solution getting people to | actually use it alongside C is hard, it has to be | _seamlessly_ seamless. Nim 's C interop is rarely used | outside of wrappers and it even more rarely is used to | produce C libraries (though perhaps that's more a fault | of incompatible type systems) | TUSF wrote: | With Zig, you just write something like: | const c = @cImport({ @cDefine("SOME_MACRO", | "1"); @cInclude("raylib.h"); }); | | Which translates the header files directly into Zig and | allows you to call into them under whatever namespace you | assigned them under. You even get completions (assuming | you're using the language server) | krupan wrote: | Honest question here (that I have every time I see someone talk | about memory safety in 2023), are you aware of Ada/Spark? | sarchertech wrote: | I tried Zig for a few weeks but ended up choosing Odin for a game | dev side project I'm working on. Odin feels a lot more high | level, but still gives you low level control when you need it. | 59nadir wrote: | I've settled on Odin as well and I think it's currently way | ahead for game development than Zig is. Even for other things | I'm currently more likely to write it in Odin, despite writing | Zig from 2019 to 2022. The reasons really come down to error | handling being better in Odin overall with payloads being | attachable to errors as well as the context system and zero | values making it relatively painless to really only talk about | the things that need talking about and letting the rest be | unsaid. | | There are also several similarities: Custom allocators as part | of the ecosystem and language, no RAII, easy ways to propagate | and handle errors the right way, tagged unions with table | stakes like exhaustiveness checking. | | I think Odin and Zig have some fundamental differences (and | plenty of similarities) and when trying Odin out I was | surprised to find that I preferred the Odin way overall. | | For gamedev stuff Odin wins due to a few things; swizzling on a | code level is super nice, array programming built-in to the | language, vendor libraries shipped with the language that allow | you to just get going almost no matter what you're doing, and | so on. | truckerbill wrote: | I want to invest in Odin but I see the velocity and growing | mindshare that Zig has and I wonder if it's not better to | settle for that. Also how do you find the compile times? | Tozen wrote: | Part of "mindshare" are organizations pushing it on social | media and marketing. Choose the language that solves your | problems and that you like. Don't make a choice because a | group is telling you what to like, is bullying others | because they like something different, or are trying to | shove something down your throat for their profit or | benefit. Perfectly fine to have an independent mind, and | make decisions best for you. | 59nadir wrote: | I think by the time I have a massive project where compile | times could actually hurt the newest endeavor with | compiling to an intermediate form, etc., will already be | released so it's likely that I'll dodge that entirely. | | For what it's worth I haven't found any language constructs | that seem to make the compile time grow considerably, so I | think the risk of adding a library and suddenly being faced | with massive compile times is fairly low in comparison to | some languages. With that said, I'm only using the core lib | and vendor libraries. | | JangaFX by way of GingerBill reports that their 200kloc | EmberGen[0] project takes 5 seconds to compile: | | > On my old machine, it took 5 seconds, and now it takes | 2.2 seconds on my new machine. | | Before some paths in the compiler had multithreading added | to them that number was 15 seconds for the same project. As | far as I know both of these numbers are for unoptimized | builds, i.e. development builds. | mr_00ff00 wrote: | Just looked at Odin and I really like the syntax, but I | feel the same way. I feel like the community and ecosystem | is the key elements and zig seems to be headed in the | direction to grab that. | sarchertech wrote: | They're very different languages despite having some | similar capabilities. | | I also found the game dev libraries in Odin far easier to | use then the ones in zig. | mr_00ff00 wrote: | Yeah I did briefly look for zig game libraries and | couldn't find much. | | I see the basic differences, but I'll have to dig deeper. | parasense wrote: | The main take away is: | | > Something that makes Zig harder to learn up front, but easier | in the long run is lack of undefined behavior. | | Reminds me of the old discussions of Fortran Vs C, and | specifically in the early times before C had a standard library. | What we call "undefined behaviour" was just an idiom of the | language where the "behaviour" was sometimes on purpose, but | recognised might not be portable. And so the point here is the | idea of undefined behaviour is tied to portability on some | levels, and isn't just some purely academic idea about the | compiler or abstract syntax trees. | | So I'm concerned about the potential over-zealous prejudice | against undefined behaviour, but I think we can all agree | deterministic software is better than otherwise. The catch is | that sometimes UB is deterministic, and yet dares to not be | idiomatic. | kps wrote: | C89's 'undefined behavior' was a failed attempt to say "you get | what the hardware gives you". | jsmith45 wrote: | Yeah. In hindsight for a fair bit of it, it could have been | sensibly changed to implementation defined behavior, or to | constrained unspecified behavior. (Constrained such that | people know what the possibilities are, but the compiler need | not document its choice, and might not make the same choice | in all circumstances. The latter could allow for scenarios | where letting an optimizer do the faster thing when | detectable, and what the hardware natively does otherwise, | for example. Obviously still a potential footgun, but less of | one than full undefined behavior). | tialaramex wrote: | This makes no sense because C89 is defined for execution on a | abstract machine, something which doesn't exist and thus has | no hardware. | | Such beliefs are however compatible with the inveterate C | programmer excuse that their nonsense programs _should_ be | correct if only the standards committee, compiler vendors, OS | designers, and everybody else in the known universe were not | conspiring to defeat their clear intent. | kps wrote: | From the C89 Rationale, "The potential for efficient code | generation is one of the most important strengths of C. To | help ensure that no code explosion occurs for what appears | to be a very simple operation, many operations are defined | to be _how the target machine's hardware does it_ rather | than by a general abstract rule. An example of this | willingness to live with _what the machine does_ can be | seen in the rules that govern the widening of char objects | for use in expressions: whether the values of char objects | widen to signed or unsigned quantities typically depends on | which byte operation is more efficient on the target | machine." | tialaramex wrote: | > _many operations are defined_ | | My emphasis. Undefined Behaviour is not an example of | operations being defined. | pklausler wrote: | Ironically, C is now way more portable than modern Fortran is. | The Venn diagram of feature portability across the 6 or 7 | actively-maintained Fortran compilers is very messy. | Symmetry wrote: | Assuming that bytes are 8 bits long or that negative numbers | are represented with two's complement is a lot less dangerous | these days than it was when C came along. | jasfi wrote: | Nim isn't hard, it just has a small community. | anta40 wrote: | I haven't done any production-level stuff with Nim (still | learning it), I think overall it's a nice language (I also like | Python & Pascal). | | If your goal is applying for job, Go is obviously a better | pick. | michaelcampbell wrote: | I don't know Zig so I can't comment much on the content, but the | author's writing style I enjoyed immensely; enough to make me | want to pick up Zig for fun. I do have some C background, albeit | decades ago, so maybe I'm in the right spot for it. | badrabbit wrote: | Everything is hard when you first learn it. If you find it easy, | that's only because you don't have to learn part of it because | you learned the concept in a different language. Even learning to | count was hard when we were small children. | | A better measure IMO is how long it might take _you_ | specifically. For example, Rust is much easier for me to learn | than Haskell because I have never coded in a functional language | before. Golang was very easy to pick up on. I never took time to | learn python and powershell, I just kept referencing existing | code and googling for examples because they were both mostly | familiar languages with a different syntax. | thadt wrote: | > Crucially, there is basically no documentation for the standard | library except for the source code itself. | | From the viewpoint of someone learning about a new language, I | find the accessibility of the standard libraries goes a long way | toward helping me understand how things fit together. It is a | first stop to see how experts in the language use it. Browsing | through the standard libraries of languages like Zig, Go, and | Python - they're usually well-documented and readable enough to | be a tutorial, even before you've dug into learning it. Others | (Rust, C++) are a bit more, ah, _technical_ for the novice. | TwentyPosts wrote: | Afaik Zig has the issue that basically everything happens on | the Discord server, where it can't be indexed via search | engines, or found by anyone who wants to have a quick question | answered. This would be "fine" if the standard library and | language were much better documented, but it isn't, and it's | still ripe with bugs. | | In other words, you're forced to use the Zig Discord server if | you want to find answers to any simple questions, and this is | (sadly) not obvious at all to newcomers to the language. | scns wrote: | The new Zulip version can make chats accessible from the | outside. In the thread about it someone wrote OSS Projects | should switch to it. | girvo wrote: | This is true for Nim as well, in that most of the discussion | is on the Discord/Matrix server. I'm not a fan personally, at | least IRC was easily archived and searchable in practice. | | I really dislike how Discord has become "forums in the 2020s" | Vecr wrote: | Rust has the standard library documentation at | https://doc.rust-lang.org/std/ or on your local computer, if | there's really nothing like that for Zig I think that's a | problem. Are you sure there's no `info zig` or something like | that? | sciolistse wrote: | There is https://ziglang.org/documentation/master/std but | it's not always been correct, and the descriptions are | lacking. The new one should hopefully fix that. | | Personally I've never had an issue reading through the source | for zig std, and if your editor supports it you can just 'go | to implementation' on most things. Hopefully the code remains | relatively readable since I find it preferable to see the | actual code + some basic tests rather than trying to navigate | those documentation sites. | tialaramex wrote: | I certainly wouldn't recommend trying to figure out C++ by | reading either of the three major C++ standard libraries. | pron wrote: | > there's not a direct correlation between the slimness of a | language's syntax and ease of learning | | That's absolutely true, but (the standard library aside) the | "syntax" -- or, rather the syntax and core semantics -- of a | programming language are arbitrary axiomatic rules, while | everything else is derivable from those axioms. So while it is | true that a small language can lead to a not-necessarily-easy-to- | learn overall programming experience, it is the only arbitrary | part, and so the only part you need to _memorise_ (or consult the | documentation for when dealing with some subtlety you may have | forgotten). So a smaller language reduces the need for "language | lawyering" _after_ you learn it. | | Some languages (e.g. lisps) are deceptively small by relying on | macros that form a "second-order" language that interacts with | the "first-order" language, but Zig doesn't have that. It has | only one language level, which is small and easy to memorise. | | But yes, Zig is a bigger language than C, but a far smaller | language than C++. What's amazing, though, is that C++ is | strictly more expressive than C (i.e. there are programs that | could grow exponentially faster in C than in C++, at least | without the help of C macros), but Zig is as expressive as C++ | (i.e. program sizes may differ by no more than a small constant | factor) while being much closer to C in size, and it achieves | that without the use of macros. | ImprobableTruth wrote: | You still have to memorize the "design patterns" that replace | 'missing' features. Especially annoying for something like | interfaces where there's a bunch of variants and people often | use implementations with awful error reporting reminiscent of | C++ templates. | | Now, it's definitely neat that you can do reasoning from first | principles on it, but I'm not sure how much of a gain that is. | mannykannot wrote: | On the other hand, Brainfuck. | the_duke wrote: | I'm not a Zig expert, but I have a different take here. | | Zig has comptime, which is essentially a compile time macro | written in the main language and with type reflection | capabilities. | | They can introduce complex behaviour and fail in very cryptic | and unexpected ways, which results in an experience very | similar to macros or C++ template literals. | pron wrote: | The objects that are manipulatable by comptime are ordinary | program objects and types -- not ASTs. That means that while | it's true you can get compile-time errors in similar | situations to macros, the errors themselves are like ordinary | runtime errors in an untyped language -- while occurring at | compile-time, they look like runtime error in Python or JS -- | rather than errors due to some "second-order" manipulation of | symbols like templates or macros, and so are easier to | diagnose (you get a regular stack trace for one). | | There is also another interesting difference, albeit a | theoretical one. Zig's comptime is what's known in formal | languages to be _referentially transparent_ (it basically | means that you cannot distinguish between two otherwise | identical objects that differ only in their reference name) | while macros are not. Because referential transparency is | strictly less expressive than "opacity" (but it's also | simpler!), it's surprising that so many practical use cases | for macros can be addressed with the less powerful (but | simpler and much easier to debug) comptime. That's quite a | discovery in language design. While other languages also have | comptime-like constructs, they also have other complex | features that have made it hard to see just how powerful | something like comptime _alone_ can be. | auggierose wrote: | It's not really surprising that purely functional | programming is expressive. Indeed, it is as expressive as | "opaque" programming. | pron wrote: | There's nothing pure functional here (perhaps the term | "referential transparency", which some FP fans have come | to misunderstand and perpetuate its misunderstanding is | what may have given you that impression). Referential | transparency is very much less expressive than | referential opacity, as there are certain statements that | simply cannot be expressed if your language is | referentially transparent. For example, in programming, a | referentially opaque expression can refer to the name of | the variable holding some value. In programming, | languages like Zig and Java are more referentially | transparent than languages like C and Haskell because the | latter have macros. | auggierose wrote: | Referentially transparent means that you can replace an | expression with its value without changing the meaning of | the program. If everything you can do must be | referentially transparent, then that's purely functional | programming, because applying functions without side- | effects is pretty much the only thing you can do then. Of | course, there are some other techniques like rewriting, | which strictly speaking are different from purely | functional programming, but I consider these two things | to be pretty much the same thing. | pron wrote: | > Referentially transparent means that you can replace an | expression with its value without changing the meaning of | the program. | | Not quite. A referentially transparent expression (E) is | one where you can replace any of its subexpressions (A) | with another (B) that has the same _meaning_ (not | value!!!!) as (A) without changing the _meaning_ (not | value!!!) of E. However, in purely functional languages, | the meaning of any expression is a value, but _that 's_ | the important thing about them, not the fact that they're | referentially transparent as imperative languages equally | are. We often use the word "semantics" or "denotation" | instead of "meaning" in the above, and we say that a pure | functional one is one that has "value semantics", i.e. | one where the meaning of an expression is a value. | | Most programming languages are referentially transparent | when not using macros (that was the whole point of | talking about referential transparency in programming in | the first place), and that's important because it | demonstrates both the expressive power and the complexity | of macros. | norir wrote: | Do you have sources for your definition? The original | definition that I'm finding from Quine seems to broadly | support the interpretation that an expression is | referentially transparent if it can be replaced by its | value without altering program semantics, as others have | stated. Regardless, it isn't clear to me how macros are | any more or less referentially transparent than function | calls in an impure language. | pron wrote: | The thing that is preserved is "meaning" or "referent" -- | the term Quine uses (hence, "reference transparency") -- | not "value". The distinction between referent/meaning and | value is the most important aspect of distinguishing | between pure FP programming languages and others, and yet | that's the thing that is so commonly confused by FPers | using the terminology, which makes it quite pointless. | | In most programming languages the reference or meaning of | a term is _not_ a value; in pure functional languages the | meaning is a value and _that 's_ what makes them special, | not their referential transparency which they share with | imperative languages. | | Here's an example from C: int global_x | = 0; void f() { x++; } void g() { | x++; } | | f and g have the same meaning in C (but the function | `void h() { x += 2; }` does not) yet `m(f)` and `m(g)` | will not have the same meaning if M is defined as: | #define m(x) #x | | However, f and g are interchangeable anywhere else (this | is not actually true because their addresses can be | obtained and compared; showing that a C-like language | retains its referential transparency despite the | existence of so-called l-values was the point of what I | think is the first paper to introduce the notion | referential transparency to the study of programming | languages: https://github.com/papers-we-love/papers-we- | love/blob/main/l... You may be surprised to see that | Strachey also uses the word "value" but his point later | is that value is not what you think it is) | norir wrote: | Thank you. That response was clarifying. I understand now | what you mean. Funnily enough though, the paper you cited | begins: | | "Any discussion on the foundations of computing runs into | severe problems right at the start. The difficulty is | that although we all use words such as 'name', 'value', | 'program', 'expression' or 'command' which we think we | understand, it often turns out on closer investigation | that in point of fact we all mean different things by | these words, so that communication is at best | precarious." | | Rather than debating the semantics of the colloquial | usage of referential transparency, I'm more interested in | the question: what can I tell at the call site of a | function without knowing the definition of the function? | In an impure language, I cannot tell whether the call has | side effects without looking at the definition. This is | true whether I am using a macro or simply a regular | function call. | | Now, even if my language of choice is impure, referential | transparency of expressions is still a useful concept | that can inform how I write my program. I can use naming, | for example, to suggest whether a function call may have | side effects even if the language compiler can't verify | the property. Not perfect, but better than nothing. And | if I'm really confused by a bug, I can always just assume | that the name is misleading and the function may have | unintentional side effects. In other words, I can use the | concept of referential transparency to implement a | metaprogramming system in my head. | whateveracct wrote: | I'm very sure the commenter is being a little pedantic | | But even pedantry can't argue that Java is a | fundamentally more referentially transparent language | than Haskell lol. That threw me for a loop. | pron wrote: | Right, the incorrect and quite pointless common use of | "referential transparency" in FP fan circles tends to | throw people off when they first see and understand the | actual meaning of the term. | whateveracct wrote: | Well it's not pointless. The term as used in FP has a | pretty well-defined meaning [1] and it is a quality only | some programs have. And a program having that quality | enhances (fast-and-loose) equational reasoning. | | [1] I can point at most Java code and prove how it fails | the definition. It's not especially hand-wavey. | auggierose wrote: | Do you have a pointer to a paper where "referentially | transparent" is defined in your sense? I grant you that | values of a programming language should be distinguished | from the meaning of an expression, which will be a value | of some sort in the logic. In that sense, _any_ language | with a denotational semantics will be referentially | transparent. So maybe what you are really saying is: | macros usually don 't have a denotational semantics. Not | sure that it is helpful to call this referential | transparency, because it differs from the meaning most | people associate with it. | whateveracct wrote: | Can you give me an example of a Haskell expression which | isn't reverentially transparent (without | unsafePerformIO)? | | > An expression is called referentially transparent if it | can be replaced with its corresponding value (and vice- | versa) without changing the program's behavior. | | ^ that is the definition of referential transparency I am | aware of. | | You seem to be implying that FPers have bastardized the | term through their misunderstanding. | | But the bog standard FP definition is a real and useful | concept. Maybe it stole something else's name? But I | don't think it's due to being mistaken. Because the FP | concept itself is pretty rigorous. | pron wrote: | > Can you give me an example of a Haskell expression | which isn't reverentially transparent (without | unsafePerformIO)? | | Yes: https://github.com/ncaq/debug-trace-var The trick, | however, is not unsafePerformIO (destructive mutability | has nothing to do with referential transparency in | general, although it breaks it in Haskell specifically) | but with TemplateHaskell, as quoting has everything to do | with referential transparency. | | > But the bog standard FP definition is a real and useful | concept. | | Actually, it's rather tautological. It defines FP | circularly (see my comment here: | https://news.ycombinator.com/item?id=36152488). It says | nothing more than the far more useful explanation: "the | meaning of every expression is a value". | whateveracct wrote: | hm okay so basically anything that doesn't use TH or | unsafePerformIO is gonna be referentially transparent. | And TH is even deferentially transparent at TH-time. It | only "breaks it" when evaluating the whole program. But | each "stage" maintains the property. | | I'm assuming any pure language with macros is also r.t. | at each stage and only pedantically breaks r.t. when | combined. But I don't think that especially hurts the | ability to do fast and loose reasoning so long as the | core language is pure. | | It definitely doesn't seem correct to say Java is more | referentially transparent than Haskell here. You don't | have to go into such niches in Java to lose that | property. | pron wrote: | > You don't have to go into such niches in Java to lose | that property. | | It's not so easy. You'd have to examine debugging | information in stack traces and use reflection. You can't | write such a "trace" operator in Java or in Zig. Of | course, without macros, C is almost perfectly | referentially transparent and Haskell is, too (except for | unsafePerformIO). | whateveracct wrote: | You can also mutate a list that is passed in and suddenly | you cannot do substitution to reason about your program. | norir wrote: | > Zig's comptime is what's known in formal languages to be | referentially transparent (it basically means that you | cannot distinguish between two otherwise identical objects | that differ only in their reference name) while macros are | not. | | In general this is true, but it is possible to write a | hygienic macro engine that is referentially transparent. | Many (likely most) macro engines are indeed unhygienic | though. I am not convinced that comptime is a better | approach than a well designed hygienic macro system but it | is an interesting research area. | Symmetry wrote: | I haven't had a chance to play with comptime in Zig yet but | I'm sort of curious how it compares to Nim's compile time | facilities. You can declare variables with 'var' for true | variables, 'let' for things that are runtime constant | within a scope, or 'const' for compile time constants whose | values can come from functions or whatever as long as it | can be resolved by the compiler. And then you've got 'when' | as a compile time equivalent of 'if'. | [deleted] | distcs wrote: | > Some languages (e.g. lisps) are deceptively small by relying | on macros that form a "second-order" language that interacts | with the "first-order" language, but Zig doesn't have that. | | What are some other examples of such languages that rely on | second-order languages? You mentioned Lisps. Would Forth be | another example? Are there more examples? | spenczar5 wrote: | I think Ruby is sometimes used in a way that looks second- | order. It allows so much metaprogramming that you can really | make a full DSL. For example, RSpec: | describe "order" do it "is marked as complete" do | expect(@order).to be_complete end it | "is not yet shipped" do expect(@order).not_to | be_shipped end end | pron wrote: | C++ templates. Also the rich type-level language in languages | like Idris (these are qualitatively different, but I'd say | they're another example of a second-language-within-a- | language that operates at a different level of objects). | ImprobableTruth wrote: | If type level functions are a "second language", then so is | Zig's comptime. | pron wrote: | It's not. comptime reifies types as regular objects | (pretty much like maps), so you're not working at the | type level; it's no more of a second language than | reflection in Java. Of course, you cannot express things | like the famous vector concatenation that's expressible | with dependent types | (https://gist.github.com/cbiffle/82d15e015ab1191b73c3) | (unless the vector sizes are known at compile time, | obviously). | KingLancelot wrote: | [dead] | ok123456 wrote: | One annoying thing I ran into when trying zig is they don't | distribute debs any more for Debian distributions. They just tell | you to use a snap. I don't have snap, and don't want it. | | Compiling it requires the latest llvm toolchian (16), which is | only realistically going to be available as a package if you're | on a bleeding edge distribution. | pacaro wrote: | I understand this, but haven't found this to be an issue | personally. I just download the pre built tarball, expand it, | make sure that /opt/zig-latest symlinks to the right folder, | and setup path | | That's more work than apt-get install for sure, but not so much | more | hellcow wrote: | You can also use something like zigup to make fetching the | latest master/managing multiple versions easier. | eatonphil wrote: | What's wrong with downloading the binary? curl + mv + chown | should do it? | netule wrote: | Zig's in the process of getting added to the mainline Debian | repositories: https://bugs.debian.org/cgi- | bin/bugreport.cgi?bug=995670 | | Hopefully, this process will continue soon as the bug seems to | be getting a bit stale. | stared wrote: | What are the use-cases in which it might be worth switching from | Rust to Zig? | epage wrote: | matklad, of rust-analyzer fame among many other things, wrote | up their thoughts on Zig: | https://matklad.github.io/2023/03/26/zig-and-rust.html | | I've seen some put it as "zig is good when `unsafe` heavy | code". | | Personally, even when writing life-or-death software, | allocation errors were too much of a pain to deal with and much | prefer Rust's approach for 99% of software. The question is if | another language like zig provides enough value to justify | existing for that 1% of use cases (all numbers made up :) ). | logicchains wrote: | When you need to be very careful about memory allocation and | use various custom allocators for stuff, and you don't care too | much about memory safety. Rust makes working with custom | allocators somewhat painful, in exchange for safety, so if you | don't need the safety, no point going through that pain. | notfed wrote: | What kinds of programs don't care about memory safety? ___________________________________________________________________ (page generated 2023-06-01 23:00 UTC)