If you haven't tried Zig since 0.16.0 was released, I highly recommend having a look. The release notes for this release were huge!!
I had some trouble understanding how the async/await mechanism works:
var foo_future = io.async(foo, .{args});
defer if (foo_future.cancel(io)) |resource| resource.deinit() else |_| {}
var bar_future = io.async(bar, .{args});
defer if (bar_future.cancel(io)) |resource| resource.deinit() else |_| {}
const foo_result = try foo_future.await(io);
const bar_result = try bar_future.await(io);
My assumption is that calling io.async using an event loop implementation of IO, it will internally start a "task" (or whatever it should be called) and that the future is a handle to it. So far so good.The part that I don't understand is what happens when you call future.await(io). Will the IO implementation somehow suspend the current function and resume once the future is resolved? If so, does that mean that every function in zig is a stackless coroutine?
the upcoming releases are expected to provide a solution to this “dispatch is comptime-known, but still dynamic” problem, and drop the loses in efficiency.
That is, I think the point was DevX not io performance.
For me it is now the go-to "tinker in my garage" language.
It doesnt let you have unused variables and theres no multiline comment support. These are fairly significant productivity issues for me
Ugh. This is something I hate about Go. I would be happy to have unused variables generate warnings, but as errors, they turn the toolchain into an adversary.
It's common for me to temporarily comment out a variable's use when developing new code, as I experiment with ideas. It's even more common when working in unfamiliar code, such as tracking down a bug or incrementally adding a new feature. It's an important part of my exploration process.
When I hit Compile at that point, I expect the compiler to build the work-in-progress exactly as it is in that moment. Executing the output allows me to spot check the snapshot's behavior against my expectations and mental model. The compile step also assures me that no syntax errors have crept in while I was focused on the logic flow or general shape of the code.
When a compiler refuses to do its job, and instead barfs up spurious errors complaining about unused variables, it brings my workflow to a screeching halt. In order to make progress, I am forced to abruptly leave my current context to visit all the different places where those variables are introduced, edit them, try again, discover that those forced edits have left more variables unused, and repeat the process until the combative compiler shuts up and does what I told it to do in the first place. By the time I'm allowed to return to what I was doing, my train of thought has been derailed, the bits of logic that I had been juggling have fallen to the ground, and my focus destroyed. And then, once I have recovered my original thoughts and seen the output of my snapshot build, I have to go back and revert all those forced edits before I can resume my work.
What an aggravating, disruptive, and completely unnecessary waste of my time and attention.
I hope Andrew has the good sense to let errors of this kind be demoted to warnings, perhaps with a compiler flag or debug build mode.
If they wanted the release build to be an error I wouldn't care. Having the current solution be "have the editor automatically change code to include or remove the underscore" is so wrong to me. Just invented a problem that needs tooling to modify source code to fix.
Multiline comments are less important, but its still convenient for commenting out large chunks of code. IDEs make this a bit easier when you can press e.g. Ctrl+/ to comment out the selected lines with //, but it doesn't work in all cases.
The friction stops zig from being fun imo. A shame because I really like comptime.
My go-to "tinker in my garage" language is Python - lightweight syntax that stays out of your face, batteries included, packages for everything that's not included. What's Zig's edge?
As for the language itself, it's going to be more verbose than your Python code. Cons: you'll have to spell out a lot of things that you thought were obvious assumptions. Pros: you will be able to look at a page of code and know with a great degree of certainty that there are no hidden gotchas. No monkey patching, no __init__. Basically, it just does what it says on the tin.
And finally, about the std lib and batteries: there's HTTP(S), compression algorithms, hash algorithms, RNG, I/O, the basic data structures you'd expect, JSON. Third-party libraries, if you choose not to vendor, are handled by including the repository url in a file (also automated by a CLI command), and then adding it to the build script (not automated). The `zig` command handles fetching and ensuring sanity, but otherwise assume a bit of elbow grease will need to be involved.
Batteries included, automatic memory management without a conventional GC and metaprogramming - is a really cool combination.
[0] - https://nim-lang.org/
Wish I had the time and skill to actually contribute to the LSP, if you have ever used Nim it's a seriously underrated language.
It's making fast progress and will provide the basis for a proper LSP! Nimony already supports incremental compilation and parallel which are key pieces for good fast LSP.
The nice thing is that all these languages feature easy C interop so you can use a C FFI as the interface between them if you want to experiment with, for example, writing a module in Nim
For the rare exceptions, I make a C lib and call into it to get my numbers crunched. I get that Zig is a viable replacement for C there. But I don't see it replacing Python.
The problem is that most people using Python don't have enough expertise in C to do the same.
It also kinda destroys the argument that Python is good if your solution for performance is to use a different language alongside it.
But... the LSPs I've tried (and I've tried a bunch!) are all atrocious: false positives and false negatives galore. Perhaps I'm spoiled by LSPs from languages with better type systems. Our code is strewn with (to me) mysterious comments such as `# NOQA 1234` which my colleague uses to make his Python tooling work with the codebase. I'm used to languages like Elm or Gleam in which a LSP error means there is an actual problem with your code, and a lack of a LSP error means the code will compile and run.
Last little project I remember is writing a solver for a puzzle game my friend published. Python just doesn't work at all for such tasks.
I think you are wrong about speed of those libraries as well. In my experience naive code designed for a specific task beats highly sophisticated general code and it doesn't take a rocket scientist to get huge speed-ups over some well established fast library.
There's not much magic in Zig. Keep hitting goto-definition and you can eventually see the OS switch statements and syscalls.
Zig is a return to “no magical effects,” except with reasonable safety
These reports are smoking crack. Rust scales gloriously well into large codebases, and it especially shines when it comes to making major refactorings. Please don't bother speaking about things that you don't understand.
Rudeness may be acceptable elsewhere. Not here.
I like Python as a tool language, and I am very impressed by projects like Micropython, but you always eventually run into a wall. I.e. you are never going to write a compute shader in python, but I assume someone is going to try.
I think the programmer should meet the hardware in the middle, and Python has a few too many layers of indirection to do this well.
Yes, in general, but also there are cases when you realize you can, idk, parse a CSV file in 0.2 seconds instead of 200 seconds. That kind of improvement unlocks a new level of tinkering.
When I want to tinker, I just want my logic to work, first of all. In 9 cases out of 10 that means going for high level. Even if the resulting code works with low level things like binary structures.
C++ adds more high-level conveniences without actually removing the footguns and undefined behavior (much C code compiles in a C++ compiler).
Zig tries to keep the low-level C philosophy but have things more well factored and well defined. The result is you _can_ tinker in high-level code, yet "drop down" into low-level code as you desire.
(Compared to rust, you get fewer compiler-enforced guarantees, but unlike C the language isn't trying to make high-level code adversarial).
I haven't really used modern C, not sure if it's evolved as much as modern C++, which I feel is a joy to use, and a lot safer. But then I've been writing C++ for decades.
I feel like C evolved from basically syntax sugar for assembly, so that's where all the footguns come from, rather than being actually adversarial.
For some reason this always brings to mind that moment in Red Dwarf where Kryten, devoid of his behavioural chip, deems it appropriate to serve roast human to his crewmates. "If you eat chicken, obviously you'd eat your own species as well, otherwise you'd just be picking on the chickens!"
It's arguably the closest modern language (with a sizeable community) to the Wirthian languages.
There is Swift as well, although quite far from Wirthian compile times.
I've been places, from embedded bare metal to ML AI, and that "embedded bare metal" end is the one place I don't use Python directly in. Embedded bare metal is just ruled by C forever.
Bit of a shame, because C is kind of bad at its job, but nothing else has the "compatible with everything" badge of honor.
The tooling around embedded devices though? Python.
If you only ever think of tinkering for the purpose of execution speed ninjutsu, isn't it your definition of tinkering that's far too narrow?
I personally think the optimization challenge is fun. I like digging in to low level stuff, reviewing the assembly dumps and processor pipeline architectures. I fail or give up most of the time, but I enjoy learning in the process.
I’m just trying to show how Zig fits my tinkering well, since you said you can’t see how Zig would ever be a good fit for tinkering. I’m not saying it’s a good fit for all forms of tinkering.
what the heck has convinced you that logic is somehow flawed in a new low-level language? LOLLL
Some people put a generator on a tesla cybertruck and call that garage tinkering.
Some people make a go-cart out of a lawnmower and call that garage tinkering.
The first is the "batteries included Python" tinkering, the second is the "low level Zig" tinkering.
There's no other language quite like Python in this regard. Typescript is a close second, but the lack of metaprogramming facilities, no access to the type annotations at runtime, and the lack of operator overloading make some things needlessly complicated and uglier than they have any right to be.
It requires more of you in some ways, notably that you have to understand the basics of memory management and the behaviour of the stack, but so far I've found the affordances that the language provides for handling this stuff feel very intuitive.
The only sharp edges I've felt so far have been the sometimes hard to guess locations of things in the standard library, and the permenant anxiety that arises from knowing I'm going to be a few more versions behind the current release with every month that passes.
I enjoy the community and culture around Zig too. The other day I found a forum thread where people were sharing what they're currently building, and there were so many fun projects from small hobbyist things to large ambitious ones. For the latter, the main concern is the stability of the language, but the good thing is that everything is out in the open, everyone knows Zig hasn't reached version 1 status - but I can see concrete steps are being made to find a good solid interface, including this I/O stuff in 0.16. As someone casually learning the language, I find it refreshing to have insight into the development process.
For whatever reasons I had to do it in Python. It was total nightmare to debug as the execution speed in debug mode was insanely slow.
I could've written it in C++ in exactly the same time and not to have any of the performance problems.
Space is valid and it compile, Tab don't --- that's it.
When one say "opinionated about how to use the language correctly", I would think JavaScript with or without end of statement semicolon and being yell at even when your program works.
This makes Cpp and Rust harder to use then say C, so C becomes the default for me. But C is not without its issues of which we are aware. But Zig feels like it could fill that sweet spot really well, being simple enough that it's easier to pick up after a long break, but still coming with a lot of modern tooling that makes programming easier.
I think that's a neat idea, but in the reverse: do as much as you can in the lower level language, and only go up to the high level language when the convenience is worth the cost.
Roc allows this: every program has a platform written in a low-level language, and then the Roc program uses the API that the platform exposes.
Then how you want to balance high vs low is of course up to you :^)
This is amazing. Didn't 0.16 take >1 year?
I was not expecting such a fast 0.17 release, but am very pleased to find this out today.
Zig’s ability to crosscompile and target arbitrary versions of glibc is PURE MAGIC. I leverage this magic in an unrelated C++ build system. But I have to hack around to get those library stubs from Zig. Would love it to be an official output.
In my experience, this (for now) is mostly aspirational. It's obviously a major goal, and there are clear milestones outlined on how to achieve it, but in practice the initial compile of an empty project or the excruciating pause when you `direnv allow` and ZLS needs to be (re)built are not what I'd describe as "terrific".
It sounds like you are a strong candidate to try out the new improvements mentioned in this devlog and see what benefits you can get for yourself.
if (2 * 2 != 5) { @panic("fail"); }
And running `zig test file.zig -OReleaseSafe` takes a couple seconds on my computer. It also keeps taking the same amount of time every time I do it when I modify that file. Using 0.16 (or master) version so my toolchain isn't old and I'm on linux.
Zig is super nice to use as a language but the compiler/stdlib isn't developed conservatively enough imo.
You may not run into an issue like this when starting out with hello world but you will want to run optimized binaries for fuzz testing or benchmarking. And then it becomes super annoying considering you might be compiling a relatively small amount of code.
Just for comparison, imo Zig is a much better language than these other languages, but if you did something like this in Rust/C++/C etc. this kind of issues basically doesn't ever happen. Assuming clang/gcc/ninja etc. usage for C/C++.
I am able to use Ninja/Python/clang for configuring/building (-O2 or -O3)/testing ~10k loc C++ project in 200ms on the same computer for example.
> if (2 * 2 != 5) { @panic("fail"); }
> And running `zig test file.zig -OReleaseSafe` takes a couple seconds on my computer.
What kind of computer are you on? I just ran that test (latest master build, first run):
~ % time zig test file.zig -OReleaseSafe
file.zig:1:17: error: expected type expression, found '{'
if (2 * 2 != 5) { @panic("fail"); }
^
zig test file.zig -OReleaseSafe 0.03s user 0.44s system 505% cpu 0.094 total
Granted I'm on an M4 Mac but I wouldn't expect another system to be 20x slower.This kind of thing just feels unacceptable considering I don't really see ANY improvement on the issues I had from back then.
Also had a similar baffling experience when I last tried to come back to writing Zig. The std.time.Instant or similar API that also exists in rust and most other languages was move to the new Io interface and they also completely removed that std.time.Instant code.
Overall it feels like people developing the tool don't respect the people using the tool. C++ or even Rust are much less enjoyable languages to write compared to Zig so it is really sad that it is not possible to actually use Zig for me.
It's different and I like it. You get one shot at it and may just as well get it right in as many areas as possible.
https://ziggit.dev/t/bun-s-zig-fork-got-4x-faster-compilatio...
That said, I hope that Zig posts won't be plagued by "but the bun thing" like this in the near future.
In any case Bun has already committed to the Rust slop switch, so it doesn't matter anymore.
zig is on its way to improving compilation times in its own pace and does so for the benefit of the project and everyone involved, so what is left to care for about bun by anthropic’s past?
Closing your eyes and pretending a problem does not exist is the a good solution. The fact of the matter is one of the biggest projects that used Zig thought that the devX was so bad that they opted to rewrite their entire 1M LOC project into a different language. This is a nightmare scenario for most companies, and will motivate similar sized companies/project to pick another language that will not require this than to risk using Zig. Also, Zig’s flippant attitude about Bun’s request (among other viewpoints) only further adds to why bigger projects would want to stay away from Zig.
That is not the fact of matter. The fact is it got bought by Anthropic. And in larger scheme of things Bun is one example Claude capabilities of translation. And even if doesn't work, it just a part of Claude desktop stack so still have millions of installs.
It's unlikely to be just a devex issue. The fact of the matter is that a memory unsafe language is an extremely tough sell today, and companies that have a security team at all have likely already made or are planning on making policies like https://chromium.googlesource.com/chromium/src/+/master/docs...
There's a reason "rewrite it in Rust" was a meme long before LLM coding tools or this Bun drama. With AI accelerated fuzzing techniques and similar, memory safety is rapidly going to become a basic requirement of anything run in a production environment.
Companies like TigerBeetle can and will benefit from zig's model.
Working together is a two-way process. To land a big change, the bun people probably needed to have been working/coordinating with the zig people throughout. E.g., zig outright cannot accept PRs that break the language in unplanned ways and any conflicts with the roadmap would need to be resolved.
I would assume the bun people know all this. That makes it more of a publicity stunt than a serious attempt to contribute to zig, and we should probably all treat it that way.
I’m not sure how well the Zig developers have handled their communication, so perhaps there really was room for improvement there.
You can't run Node on embedded systems, because there isn't enough memory.
A compiled zig program can be only several kilobytes with no depedenencies.
Array access programmed in low-level languages can be optimized with SIMD and parallelization, which will be orders of magnitude faster than the same thing on Javascript. Text processing, image manipulation, video processing, hashing, etc.
There is like infinite reasons to not use Javascript.
Is it not possible to build a wrapper that does this? It seems like it should be.
For comparison, while Rust offers a very rich string library, it's also very strict about what you can/cannot do with strings, so if your use case falls outside of that you're out of luck. With Zig, you can pretty easily roll your own and make it do what you want. (and when Zig is post 1.0, I imagine there will be some very nice pre-made string libraries by the community etc.)
In C you have pain. Does the caller allocate a buffer? How does it know how big to make it? Do you have to have separate calls to calculate the required length? Etc. Can Zig work like Rust/C++ and not like C? My impression is that it can't.
For example, I find Rust to be far too similar to C++, and it shares most of the problems I have with C++ only with much lower adoption. I'm not saying I'm ready to make the switch, but at least Zig offers a different approach that's intriguing to me.
Do not try it if you are scared of memory management and memory leaks.
For small, short game dev, or even smaller embedded projects, this ends up being a wonderful way to live as often times you're trying to eke out performance in ways that would require breaking out of whatever type abstractions or using unsafe.
For long-lived systems, for systems that need to have lots of people with various skill levels work on them, for a mature ecosystem, for a language/standard library with stability... You probably don't want to pick Zig right now. Some of these points will change over time with Zig becoming more mature, some won't. Zig will always be super cool to build things in.
As far as most low-level programmers not liking Rust like some other commenters say, lol, lmao even.
The "Expat" here is the MIT license variant. It is referring to the Expat XML parsing library that first used this license.
Usually when projects these days use an MIT license this is the version they use.
I'm not even thinking of AI, but Rust. I guess I'm just uninterested in a "modern C".