<story><title>Why I rewrote my Rust keyboard firmware in Zig: consistency, mastery, and fun</title><url>https://kevinlynagh.com/rust-zig/</url></story><parent_chain><item><author>simias</author><text>I admit that I&amp;#x27;m a Rust fanboy so it probably wraps my view a bit, but from personal experience I don&amp;#x27;t consider unlimited compile-time code execution to be a completely good thing.&lt;p&gt;Yes, it makes the language more approachable, yes it makes it easier for people who aren&amp;#x27;t familiar with the language to understand what&amp;#x27;s going on. That&amp;#x27;s nice, but that&amp;#x27;s not critically important IMO. It&amp;#x27;s nice if you want to impress people on HN, but if you use the language day-to-day you&amp;#x27;ll get over that stuff pretty quickly.&lt;p&gt;On the other hand this type of extreme customization means that even for somebody very familiar with the language you still have to be on your toes because innocuous looking code could behave surprisingly due to comptime shenanigans. On the other hand languages with a more rigid structure may end up being more verbose but that leads to code that a proficient coder can unambiguously understand without having to mentally expand comptime blocks or macros.&lt;p&gt;This is effectively the metaprogramming equivalent of the statically vs dynamically typed debate. Yes, dynamic code is easier to write but it can be harder to maintain and leads to worse compiler diagnostics and generally requires more unit tests to validate that it&amp;#x27;s doing the right thing. I think macros&amp;#x2F;comptime behave similarly when compared to stricter, more limited metaprograming like Rust&amp;#x27;s generics system.&lt;p&gt;Rust has macros too of course, but they&amp;#x27;re a pain to write in my experience, and I&amp;#x27;d almost argue that it&amp;#x27;s a feature. You only use them if you really have to, and after careful consideration, or at least that&amp;#x27;s how I use them.</text></item><item><author>dilap</author><text>Here&amp;#x27;s another example of the coolness of Zig&amp;#x27;s comptime code execution:&lt;p&gt;&lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;ziglang&amp;#x2F;zig&amp;#x2F;commit&amp;#x2F;0808d98e10c5fea27cebf912c6296b760c2b837b&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;ziglang&amp;#x2F;zig&amp;#x2F;commit&amp;#x2F;0808d98e10c5fea27cebf9...&lt;/a&gt;&lt;p&gt;That&amp;#x27;s a generic container class (similar to vector in C++ or List in C#). But! With a twist!&lt;p&gt;It stores structs in &amp;quot;column major&amp;quot; order in memory (e.g., if a struct had two fields A and B, then in-memory layout would be A...AB...B), and you can idiomatically and efficiently get a a slice of the values of each column.&lt;p&gt;I.e., it&amp;#x27;s a datastructure that automatically applies the struct-of-arrays optimization:&lt;p&gt;&lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;en.m.wikipedia.org&amp;#x2F;wiki&amp;#x2F;AoS_and_SoA#Structure_of_Arrays&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;en.m.wikipedia.org&amp;#x2F;wiki&amp;#x2F;AoS_and_SoA#Structure_of_Arr...&lt;/a&gt;&lt;p&gt;And the code to do it is straightforward, normal Zig.&lt;p&gt;Pretty awesome stuff!</text></item></parent_chain><comment><author>pron</author><text>Zig doesn&amp;#x27;t have unlimited compile-time execution and what it has is strictly weaker than Rust&amp;#x27;s macros [1]. Rather, it has one carefully designed construct that is both very simple and very expressive, and yet isn&amp;#x27;t as weird or as dangerous as macros. It is not &amp;quot;extreme customisation&amp;quot; but just the right amount to make the language both simple and expressive &lt;i&gt;without&lt;/i&gt; extreme measures like macros. Zig accepts that macros are problematic, and shows how far you can go without them altogether. OTOH, while macros are common enough in Rust that while you may not write them yourself all the time, you do use them frequently.&lt;p&gt;I guess that there is some small truth to your allusion to the static-vs-dynamic debate, but Zig does give you errors at compile-time, and elaborate things it can check at runtime are much easier to express than in Rust. But I would say that Rust is a language in a well-known tradition, and is clearly a &amp;quot;cleaned up C++&amp;quot;, while Zig is something that we haven&amp;#x27;t seen before. It is not dynamic in the same sense as dynamic languages -- you get the checks done at compile-time -- but it is not part of the familiar tradition of typed languages or even any low-level language.&lt;p&gt;I&amp;#x27;m not a devout minimalist, but when it comes to low-level programming in particular, language simplicity is a very important feature, and before Zig it wasn&amp;#x27;t clear it was achievable at all in low-level languages without significantly compromising on expressivity and safety.</text></comment>
<story><title>Why I rewrote my Rust keyboard firmware in Zig: consistency, mastery, and fun</title><url>https://kevinlynagh.com/rust-zig/</url></story><parent_chain><item><author>simias</author><text>I admit that I&amp;#x27;m a Rust fanboy so it probably wraps my view a bit, but from personal experience I don&amp;#x27;t consider unlimited compile-time code execution to be a completely good thing.&lt;p&gt;Yes, it makes the language more approachable, yes it makes it easier for people who aren&amp;#x27;t familiar with the language to understand what&amp;#x27;s going on. That&amp;#x27;s nice, but that&amp;#x27;s not critically important IMO. It&amp;#x27;s nice if you want to impress people on HN, but if you use the language day-to-day you&amp;#x27;ll get over that stuff pretty quickly.&lt;p&gt;On the other hand this type of extreme customization means that even for somebody very familiar with the language you still have to be on your toes because innocuous looking code could behave surprisingly due to comptime shenanigans. On the other hand languages with a more rigid structure may end up being more verbose but that leads to code that a proficient coder can unambiguously understand without having to mentally expand comptime blocks or macros.&lt;p&gt;This is effectively the metaprogramming equivalent of the statically vs dynamically typed debate. Yes, dynamic code is easier to write but it can be harder to maintain and leads to worse compiler diagnostics and generally requires more unit tests to validate that it&amp;#x27;s doing the right thing. I think macros&amp;#x2F;comptime behave similarly when compared to stricter, more limited metaprograming like Rust&amp;#x27;s generics system.&lt;p&gt;Rust has macros too of course, but they&amp;#x27;re a pain to write in my experience, and I&amp;#x27;d almost argue that it&amp;#x27;s a feature. You only use them if you really have to, and after careful consideration, or at least that&amp;#x27;s how I use them.</text></item><item><author>dilap</author><text>Here&amp;#x27;s another example of the coolness of Zig&amp;#x27;s comptime code execution:&lt;p&gt;&lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;ziglang&amp;#x2F;zig&amp;#x2F;commit&amp;#x2F;0808d98e10c5fea27cebf912c6296b760c2b837b&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;ziglang&amp;#x2F;zig&amp;#x2F;commit&amp;#x2F;0808d98e10c5fea27cebf9...&lt;/a&gt;&lt;p&gt;That&amp;#x27;s a generic container class (similar to vector in C++ or List in C#). But! With a twist!&lt;p&gt;It stores structs in &amp;quot;column major&amp;quot; order in memory (e.g., if a struct had two fields A and B, then in-memory layout would be A...AB...B), and you can idiomatically and efficiently get a a slice of the values of each column.&lt;p&gt;I.e., it&amp;#x27;s a datastructure that automatically applies the struct-of-arrays optimization:&lt;p&gt;&lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;en.m.wikipedia.org&amp;#x2F;wiki&amp;#x2F;AoS_and_SoA#Structure_of_Arrays&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;en.m.wikipedia.org&amp;#x2F;wiki&amp;#x2F;AoS_and_SoA#Structure_of_Arr...&lt;/a&gt;&lt;p&gt;And the code to do it is straightforward, normal Zig.&lt;p&gt;Pretty awesome stuff!</text></item></parent_chain><comment><author>lhorie</author><text>I don&amp;#x27;t think comparing zig&amp;#x27;s comptime with rust macros is actually that apt of a comparison. I tend to think of rust macros as syntactic sugar. Zig&amp;#x27;s comptime permeates the language thoroughly and in fundamental (and IMHO very pragmatic) ways. Top level const expressions are automatically comptime, modules are comptime structs, static polymorphism is used all over the stdlib (e.g. std.mem.eql), heck std.debug.print is written without special compiler tricks thanks to how cleanly you can use comptime in zig.&lt;p&gt;I think the idea that zig is a very sharp knife is true, but the overlap of footguns and comptime is not as big as one would think (@fieldParentPtr mistakes comes to mind, but that&amp;#x27;s sort of about it)</text></comment>