7 ms·
Zig cookbook: collection of simple Zig programs that demonstrate good practices
- latch 3y agoThe first example, reading lines in a file, is really slow. Depending on the input, it could be 4x-10x slower. In Go, the equivalent `ReadLine` is implemented on `bufio.Reader`. Thus the implementation can take advantage of the buffering. In Zig, while this example does use a BufferedReader, the `streamUntilDelimiter` is implemented on the more generic `std.io.Reader` and thus cannot take full advantage of the buffering. It checks 1 byte at a time, and cannot leverage the SIMD-optimized `std.mem.indexOfScalar`. Of course, you're free to create your own `readLines` that works against a BufferedReader. I do hope we'll see a whole version dedicated to review/polishing of the standard library. And maybe more work on composition, abstraction and interfaces. The issue is described here: https://github.com/ziglang/zig/issues/17985 https://github.com/ziglang/zig/issues/17985
- anonymoushn 3y agoThanks for highlighting this. Internally we're mostly avoiding the parts of the std Reader interface that impose significant runtime costs if you use them, but it would be swell to upgrade the stdlib implementations to do something like golang interface upgrades for buffered readers.
- synergy20 3y agohonestly I still don't get why I need zig, modern c seems just fine for daily coding, what are the must-see selling points that can attract c programmers to switch?
- kiitos 3y agoThe long history of C has demonstrated pretty clearly that it's not possible for humans to write C (at scale) that is free of vulnerabilities.
- hansvm 3y agoI could list features, but as an otherwise happy C programmer I can confidently state that Zig makes it substantially easier to write fast, correct programs, be sure they're correct, and maintain those two properties as I modify those programs. A smattering of points to look at include comptime (replacing the preprocessor [0], scripted lookup tables, generics, ...), non-null pointers, the community ethos of a principle of least power (e.g., any part of the stdlib you'd expect could be used on an embedded device can in fact be used there), exhaustive switching, cross-compilation, and errdefer. [0] Not being textual is the source of comptime's power, but you'll never do something like write Zig code that looks like Fortran. Comptime adds some capabilities and takes away others. The tradeoff is pretty positive IMO.
- pjmlp 3y agoZig might not be the answer, but so isn't "modern" C, if security is something one cares about. If it is only about being a more portable Assembly like language, provided the CPU is a PDP-11 descendent without any additional compute units like SIMD or GPU, then yeah, C might be good enough.
- anonymoushn 3y agoC has a better SIMD story than Rust or Zig currently.
- pjmlp 3y agoNot really, some C compilers have language specific extensions that exposed SIMD, C as defined by ISO and POSIX, does not. Rust has them as part of the language, as does .NET, D, as will C++26 get, eventually Java as well,...
- anonymoushn 3y agoRust hides operations like register-register vpshufb behind unsafe despite this instruction having no implications for memory safety and crashing on CPUs that don't support it (just like auto-vectorized "safe" code built for a different set of extensions than the CPU it's running on). Zig formerly exposed a subset of SIMD operations via LLVM intrinsics, but this was a bug and was fixed, so we now must use inline assembly to recreate immintrin.h and arm_neon.h.
- pjmlp 3y agoDoesn't change the fact that neither immintrin.h or arm_neon.h. are listed on ISO C, or POSIX standards.
- anonymoushn 3y agoDoes this matter? Rust and Zig have no standard. Each has fewer compilers than C has compilers that ship these headers.
- flohofwoe 3y agoIn short: Zig can (and does) fix C warts from the ground up because it doesn't need to be backward compatible with C, while still getting the essence of what makes C useful (many other new languages don't get this important part). The biggest advantage over C for day-to-day coding is probably the much more complete and useful stdlib. You also don't need to "switch", mixed C/Zig projects are well supported by the Zig language and build system. Having said that, I still write most new code in C (C99 designated init is still superior to what Zig has to offer for struct initialization), but at least there's now a worthwhile alternative on the horizon to switch to in the future.
- triyambakam 3y ago> C99 designated init is still superior to what Zig has to offer for struct initialization Can you explain this for the ignorant?
- flohofwoe 3y agoWhen initializing a struct, Zig currently doesn't allow chained designators and also doesn't allow to partially initialize arrays and have the rest of the array filled up with default values (the first one isn't all that important, but the second is). E.g. the closest Zig equivalent to this C99 code: https://github.com/floooh/sokol-samples/blob/b3bc55c4411fa03770e2ff4303e1d49f9f36616d/sapp/texcube-sapp.c#L120-L136 https://github.com/floooh/sokol-samples/blob/b3bc55c4411fa03... ...is this: https://github.com/floooh/sokol-zig/blob/a4b3c287fadd153a5046f6fd4b35f4118b25fe53/src/examples/texcube.zig#L106-L118 https://github.com/floooh/sokol-zig/blob/a4b3c287fadd153a504... ...note how part of the initialization had to be moved out into separate assignments, which means the struct can't be created as const. There's a ticket about this here, but it's currently not high-priority: https://github.com/ziglang/zig/issues/6068 https://github.com/ziglang/zig/issues/6068 Zig also isn't alone in this, I haven't encountered any other programming language yet which has such a flexible struct initialization syntax as C99. Odin is probably the closest I've seen yet. https://github.com/floooh/sokol-odin/blob/084c2429bd52b8d9dc852f77947cd248b106718f/examples/texcube/main.odin#L115-L130 https://github.com/floooh/sokol-odin/blob/084c2429bd52b8d9dc...
- alex_lav 3y agoIs someone telling you you need zig?
- throwawaymaths 3y ago- No preprocessor nonsense - typesafe metaprogramming (usually no void* type erasure) - sane legibility of complicated types - (for beginners) not having to learn/deal with make - corrects the long long mistake (yes, I get that everyone uses inttypes.h now) - alignment aware pointer types - null aware pointer types - null terminated string aware pointer types - slices (fat pointers?) default - sane cross-compilation - errors returned as values, no errno weirdness - no pass-by-value/pass-by-reference ambiguity (const correctness by default) At least four of these are footguns my highly experienced coworkers would have avoided this last week of work alone. It's possible that as a longtime c developer, you have internalized the biggest problems with c, especially the ones that trip up beginners. Maybe zig is not for you. If you start using zig, you just may start wanting to throw your desk out the window every time you have to go back to c, which is not really worth the effort/employmemt sanity risk.
- lgkk 3y agoIs make considered bad or something? I use make and I mostly program in Go. It seems to make my life pretty simple. What is an alternative?
- dureuill 3y ago> Is make considered bad or something? Depends what you're using it for. Generated from CMake, Makefiles are OK I guess, although Ninja is strictly better these days. Manually written, I would say make is bad. 1. It doesn't promote portability: since each target calls shell commands, it is very easy to accidentally create a non portable Makefile (something alleviated when using CMake that handles the portability before emitting the Makefile) 2. It is imperative and stateful in subtle ways, which is the wrong level of abstraction for a build system. Systems that are declarative and describe the desired state of the build are much easier to use and reliable 3. It is bare bone as far as build system functionality goes: it doesn't provide many of the useful things I expect from a modern build system: the concepts of library dependencies, build profiles, compiler flags, test, documentation or even project in general... are all orthogonal to make 4. It is ad-hoc: as a result of the previous points, the expected functionality of a build system is often re-created in the makefile, but in a non fully standard way (conventions exist, but must be manually enforced and are limited). This results in brittle and difficult to use build systems. > What is an alternative Language-specific package managers, notably Cargo. If using rust, there's also a pattern called xtask[1] that's aiming at providing a standard interface in the form of a binary (since it is rust, it is portable, but most of the other points unfortunately apply). Otherwise, CMake, meson, nix, bazel, buck2 [1]: https://github.com/matklad/cargo-xtask https://github.com/matklad/cargo-xtask
- throwaway17_17 3y agoGenuine question: what do you mean by ‘daily coding’? I certainly find C acceptable, if not compelling, for doing widely portable, memory and speed sensitive software engineering, but that is not what I would typically associate with ‘daily coding’ tasks. I would normally use that term to signal thing like data, task, and OS automations (i.e. scripting, command line convenience apps, text/binary file compression/search/reorganization). Not knocking your answer, just trying to get your intended meaning to evaluate whether I agree with the particular use case as a fit for a language as minimal and manual as C.
- synergy20 3y agoI do embedded stuff so C is the primary language, sometimes C++ as well.
- throwaway17_17 3y agoThat’s cool, for you C is in fact a daily coding language and I’m probably a little jealous that you get to do low level, performance critical work regularly.
- AndyKelley 3y agoIn short: zig offers a massive productivity boost, while delivering less buggy and more efficient software.
- computerbuster 3y agoI just started C and Zig at the same time in October. While Zig was not easy to learn right away, in my opinion, it has become a joy to work with as I've become more familiar with it. This isn't to say learning C is a useless exercise in futility, but I think people not understanding why Zig is cool might need to remember they may be more experienced and more accustomed to things about C that are hard to get used to as a beginner.
- WantonQuantum 3y agoThe threads example (https://zigcc.github.io/zig-cookbook/07-01-spawn.html https://zigcc.github.io/zig-cookbook/07-01-spawn.html) doesn't run the threads in parallel. It spawns the first thread and waits for it to finish and then spawns the second thread and waits for that to finish. The fix is to move t1.join() to after the second thread is created.