TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

A Review of the Zig Programming Language (Using Advent of Code 2021)

341 点作者 mkeeter超过 3 年前

24 条评论

travisgriggs超过 3 年前
Computer language inventors are torn between a voice whispering “use the language Luke” and and a more gravelly “let your feelings for the compiler grow, embrace the syntax side.”<p>I did a two-day sprint through Zig a month ago and really really liked it. It has some quirks that I would have done differently, but overall I think it’s pretty cool. I just need a good small scale project to try it out on now.<p>My favorite example of the “use the language” ethos is the way Zig does generics. I have hated generics&#x2F;templates in every language I use them in. They are the gordian knot of confusion that most languages in pursuit of some sort of unified type theory impale themselves on (yes, I’m mashing metaphors here). But Zig just uses its own self to define user types and generics come along for free. It resonates (with me at least) as a realization of what Gilda Bracha has shared about how to reify generics.<p>[1] <a href="https:&#x2F;&#x2F;gbracha.blogspot.com&#x2F;2018&#x2F;10&#x2F;reified-generics-search-for-cure.html?m=1" rel="nofollow">https:&#x2F;&#x2F;gbracha.blogspot.com&#x2F;2018&#x2F;10&#x2F;reified-generics-search...</a>
评论 #29705816 未加载
评论 #29706317 未加载
评论 #29705642 未加载
AnIdiotOnTheNet超过 3 年前
&gt; Initializing arrays is weird in Zig. Lets say you want to have a 0 initialized array, you declare it like [_]u8{0} * 4 which means I want an array, of type u8, that is initialized to 0 and is 4 elements long. You get used to the syntax, but it’s not intuitive.<p>Alternatively:<p><pre><code> var some_array = std.mem.zeroes([4]u8); </code></pre> Though as mentioned later in the article the standard library documentation is not very good, making this not as obvious as it could be.<p>&gt; Everything in Zig is const x = blah;, so why are functions not const bar = function() {};?<p>Good question, there&#x27;s an accepted proposal to fix this: <a href="https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;1717" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;1717</a><p>&gt; The builtin compiler macros (that start with @) are a bit confusing. Some of them have a leading uppercase, others a lowercase, and I never did work out any pattern to them.<p>In idiomatic zig, anything that returns a type is uppercased as though it were itself a type. Since only a few builtins return types, the vast majority of builtins will start with a lowercase letter. I think it is only `@Type`, `@TypeOf`, `@This`, and `@Frame` that don&#x27;t.
评论 #29703341 未加载
评论 #29704904 未加载
评论 #29704623 未加载
anatoly超过 3 年前
I also did AoC 2021 in Zig: <a href="https:&#x2F;&#x2F;github.com&#x2F;avorobey&#x2F;adventofcode-2021" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;avorobey&#x2F;adventofcode-2021</a><p>One thing the OP didn&#x27;t mention that I really liked was runtime checks on array&#x2F;slice access and integer under&#x2F;overflow. Because dealing with heap allocation is a bit of a hassle, I was incentivized to use static buffers a lot. I quickly figured out that I didn&#x27;t have to worry about their sizes much, because if they&#x27;re overrun by the unexpectedly large input or other behavior in my algorithms, I get a nice runtime error with the right line indicated, rather than corrupt memory or a crash. Same thing about choosing which integer type to use: it&#x27;s not a problem if I made the wrong choice, I&#x27;ll get a nice error message and fix easily. This made for a lot of peace of mind during coding. Obviously in a real production system I&#x27;d be more careful and use dynamic sizes appropriately, but for one-off programs like these it was excellent.<p>Overall, I really enjoyed using Zig while starting out at AoC problem 1 with zero knowledge of the language. To my mind, it&#x27;s &quot;C with as much convenience as could be wrung out of it w&#x2F;o betraying the low-level core behavior&quot;. That is, no code execution hidden behind constructors or overloads, no garbage collection, straight imperative code, but with so much done right (type system, generics, errors, optionals, slices) that it feels much more pleasant and uncomparably safer than C.<p>(you can still get a segmentation fault, and I did a few times - by erroneously holding on to pointers inside a container while it resized. Still, uncomparably safer)
评论 #29705568 未加载
评论 #29703932 未加载
评论 #29710008 未加载
dnautics超过 3 年前
&gt; Everything in Zig is const x = blah;, so why are functions not const bar = function() {};?<p>This may or may not happen: <a href="https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;8383" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;8383</a><p>&gt; Fixing the standard library documentation would be my biggest priority if I worked on Zig, because I think that is the only thing holding back general usage of the toolchain.<p>This is a valid concern, but I believe the zig team is deliberately holding off on improving the std lib documentation, because they are expecting (potentially huge, maybe not? who knows) breaking changes down the line. The &quot;stdlib is not documented&quot; is a deliberate choice to signal &quot;use at your own risk, especially with respect to forwards compatibility&quot;.<p>&gt; there are still quite a few bits of syntatic sugar hiding the real cost of certain operations (like the try error handling, there is implicit branches everywhere when you use that...<p>I dunno, that&#x27;s like saying that `if` hides branching. It&#x27;s a language-level reserved word, you&#x27;re expected to understand how they work under the hood.
评论 #29703400 未加载
dureuill超过 3 年前
&gt; Try and read a moderately complex Rust crate and it can be mind boggling to work out what is going on.<p>I do that all the time, even reading the source of the std, something that I cannot do sanely in C++. IME Rust code is easy to read, with symbols that are always either defined in the current file, imported, or referred to by their full path.
评论 #29705024 未加载
评论 #29703923 未加载
评论 #29704963 未加载
评论 #29703392 未加载
评论 #29708473 未加载
flohofwoe超过 3 年前
The part about making things easy to type is interesting, because this generally only works with a single international keyboard layout (usually US English), e.g. making things easy to type on the US keyboard layout may make it harder on an international layout.<p>It&#x27;s an old problem though, for instance the {}[] keys are terribly placed on the German keyboard layout, requiring the right-Alt-key which was enough for me to learn and switch to the US keyboard layout, and not just for coding.<p>I think a better approach for a programming language would be to use as few special characters as possible.<p>PS: Zig balances the &#x27;|&#x27; problem by using &#x27;or&#x27; instead of &#x27;||&#x27; ;)
评论 #29708853 未加载
评论 #29704747 未加载
评论 #29704883 未加载
typon超过 3 年前
While the standard library documentation is non existent, using grep on it and just reading through it is very easy, compared to almost any other language I have used.<p>I would actually say this is preferred: it&#x27;s early days, so the documentation can&#x27;t go out of sync because it doesn&#x27;t exist, and library maintainers are incentivized to write understandable code, which most people who are getting into the language are forced to read, creating a consensus of what is considered idiomatic in the community.
评论 #29704645 未加载
评论 #29705223 未加载
e12e超过 3 年前
&gt; For loops are a bit strange too - you write<p><pre><code> for (items) |item| {} </code></pre> &gt;, which means you specify the container before the per-element variable. Mentally I think of for as for something in many_things {} and so in Zig I constantly had to write it wrong and then rewrite.<p>That does feel like the syntax is missing an &quot;each&quot; or a &quot;with&quot;, as in &quot;for each somethings as some do&quot; or &quot;with each somethings as some&quot; - or in a similar terse&#x2F;compact syntax:<p><pre><code> each (items) |item| {} </code></pre> I&#x27;m surprised there&#x27;s no mention about (lack of) string type - considering the domain (advent of code). I&#x27;ve not found the time to actually work on aoc this year, but I also had a brief look at starting with Zig - and quickly met a bit of a wall between the terse documententation on allocator, and the apparent lack of standard library support for working with strings.<p>I think the documentation will improve as the language stabilizes and there&#x27;s likely to be more tutorials that work with text (both trivial like sirt&#x2F;cat&#x2F;tac in zig, and more useful like http or dns client and servers etc).
评论 #29703902 未加载
评论 #29704383 未加载
评论 #29703968 未加载
评论 #29703687 未加载
评论 #29703672 未加载
gilbetron超过 3 年前
&gt; One nugget of knowledge I’ve worked out though - Zig is not a replacement for C. It is another replacement for C++.<p>I hope this isn&#x27;t the case, since I see Rust as the C++ replacement, and another replacement isn&#x27;t very interesting to me. The main reason I&#x27;ve been interested in Zig is because I thought it was a replacement for C, which is an interesting idea.
评论 #29703639 未加载
评论 #29705636 未加载
评论 #29706043 未加载
评论 #29704621 未加载
formerly_proven超过 3 年前
The optionals story in Zig seems a bit weak to me, because it has dedicated syntax to support conditional unwrapping:<p><pre><code> if(optional) |captured_optional| { ... } </code></pre> if actually is three different syntaxes:<p><pre><code> if(expression) {} else {} if(optional) |captured| {) if(optional) |captured| {) else {} if(errunion) |result| {} else |err| {} </code></pre> The latter is kinda awkward because it looks exactly like the optional syntax until the else and you have to know the type of the variable to know which is which. Capturing doesn&#x27;t allow shadowing, which makes the optional case awkward.<p>This is one area that e.g. Kotlin has done better by checking if the expression of any if statement implies non-nullity of variables and then implicitly unwrapping them, as they can&#x27;t ever be null:<p><pre><code> if(optional != null) { use optional directly } </code></pre> This works much better for multiple optionals:<p><pre><code> if(optA != null &amp;&amp; optB != null) { can use both optA and optB directly } </code></pre> You can write this in Zig as well, but it results in a sea of unchecked .?, while Kotlin while give you compile errors if you use an optional without unwrapping that was not implied to be non-null.<p>Or you go multiple levels deep, as the if-optional syntax only allows one optional:<p><pre><code> if(optA) |capturedOptA| { if(optB) |capturedOptB| { } } </code></pre> The error union story is fairly sound so far but one major annoyance is that while it composes well for returning errors, it doesn&#x27;t compose well for error handling. You can&#x27;t do:<p><pre><code> someComplexThing(file1, file2) catch |err| switch(err) { CryptoErrorSet =&gt; handle_crypto_error(err); FileErrorSet =&gt; ... } </code></pre> as switch does not support error sets for branches, only error values. This seems to me like it incentivizes you to do have either something like this:<p><pre><code> someComplexThing(file1, file2) catch |err| { if(cryptoErrorToString(err)) |errdescription| { &#x2F;&#x2F; ... } if(ioErrorToString(err)) |errdescription| { &#x2F;&#x2F; ... } } </code></pre> Or just a huge handleAllTheErrorsPls thing.<p>Errors are also just a value - if you want some extra information&#x2F;diagnostics to go along with an error, you&#x27;ll have to handle that yourself out-of-band.<p>On errors, Zig doesn&#x27;t seem to have a strerror for std.os errors - awkward.
评论 #29704993 未加载
anonymoushn超过 3 年前
&gt; One nugget of knowledge I’ve worked out though - Zig is not a replacement for C. It is another replacement for C++.<p>While comptime is a potential source of complexity, I sort of think C++ developers won&#x27;t accept a replacement that has no RAII or automatic invocation of destructors.
评论 #29703281 未加载
评论 #29706478 未加载
balaji1超过 3 年前
I got into Rust by working on Advent of Code 2021. The problems seem arbitrary, repetitive and sometimes unnecessarily hard. But they are well-designed for starting on a new language. We are forced to repeatedly use basic concepts of a language, so that is useful to get a few reps in on a new language. We are also forced to build utils that can be used a few times.<p>And if you challenge yourself to solve the problem as quickly as possible so as to see where the story leads, you can stay motivated to work thru the problems. Helps if you have a friendly competition going with a few friends.
guidorice超过 3 年前
&gt; I wanted something more like Rust’s cargo test that’d find all tests and run them. Maybe Zig does have this but I just didn’t find it?<p>Try `zig build test`<p><a href="https:&#x2F;&#x2F;ziglang.org&#x2F;documentation&#x2F;master&#x2F;#Zig-Build-System" rel="nofollow">https:&#x2F;&#x2F;ziglang.org&#x2F;documentation&#x2F;master&#x2F;#Zig-Build-System</a>
评论 #29709762 未加载
评论 #29706237 未加载
ptrwis超过 3 年前
If dereferencing the pointer is through ptr.*, wouldn&#x27;t it be more consistent to take the address with myvar.&amp; instead of &amp;myvar?
OtomotO超过 3 年前
The one thing I personally love about Zig, from an outsiders perspective, is the relatively clear scope and the &quot;no, we won&#x27;t add each and every feature we can imagine&quot;-stance.<p>It also seems rather elegant.
评论 #29705133 未加载
fmakunbound超过 3 年前
&gt; and so making getting at heap allocations harder by explicitly getting them through an allocator is a great thing.<p>Did not follow this logic.
评论 #29703936 未加载
hota_mazi超过 3 年前
Can someone more knowledgeable than me in Zig explain this:<p>&gt; var x = try foo(); means x is equal to the result of foo() unless there was an error in the result.<p>&gt; If there was an error, return from the function with the error now.<p>&gt; This meant that you don’t have the messy littering of if conditionals after every function that you<p>&gt; typically get in C, but you also don’t have the complete disaster that is exceptions in C++&#x2F;C#.<p>How is this different from exceptions?<p>Exiting a function immediately in case a function call fails sounds exactly like an exception.
评论 #29709122 未加载
评论 #29709047 未加载
arch_rust超过 3 年前
There is an open issue for something like `cargo test` <a href="https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;10018" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;10018</a>
ncmncm超过 3 年前
All it needs to be actually useful is destructors. And, constructors.<p>I am always amazed when a new language omits destructors. Sure, CS assignments don&#x27;t need them, but out here we have real resources, not just memory, to manage.
评论 #29706136 未加载
评论 #29706373 未加载
评论 #29706083 未加载
评论 #29713354 未加载
kaba0超过 3 年前
How does it compare to other C-replacement languages, like Beef?
butterisgood超过 3 年前
Zig is definitely a C replacement in my opinion.<p>I agree about the array and pointer syntax being hard to remember.<p>I’ve high hopes for the language.
adamrezich超过 3 年前
&gt; For loops are a bit strange too - you write for (items) |item| {}, which means you specify the container before the per-element variable. Mentally I think of for as for something in many_things {} and so in Zig I constantly had to write it wrong and then rewrite. Also you use the | character in Zig quite a lot, and while this may just be a problem with Apple UK keyboards, actually getting to the | character on my laptop was uncomfortable. When doing C&#x2F;C++ or Rust, you use the | character much less and so the pain of writing the character was something I never noticed before. Jonathan Blow has gone on the record to say that with his language, Jai, he spent a lot of time working out how easy it would be to type common things, such that the more common an operation in the language, the easier it would be to type.<p>I&#x27;ve written much more &quot;Jai&quot; than Zig but this is one of the things that stuck out to me the most in Zig&#x27;s syntax as being strange. in &quot;Jai&quot;, for loops iterate over arrays, ranges (0..10), or anything else that has a for_expansion defined for it. implicitly, &quot;it&quot; is the iterator and &quot;it_index&quot; is the index. to for-loop over an array, you simply write<p><pre><code> foos: [..] int; for foos { &#x2F;*...*&#x2F; } </code></pre> if you don&#x27;t want to use it and it_index, likely because you&#x27;re nesting loops, you write<p><pre><code> for foo: foos { } for foo, foo_index: foos { } </code></pre> this has some very nice properties in addition to relative terseness: when you want to iterate over something, which is something you do all the time in all kinds of contexts, you just write &quot;for foos do_something_to_foo(it);&quot; suddenly you find you need to use something other than the implicit it&#x2F;it_index, so you just change it to &quot;for foo: foos do_something_to_foo(foo);&quot; maybe when you&#x27;re &quot;sketching out&quot; your program code, &quot;foos&quot; is just an array of ints, but as you flesh things out further, you realize you want it to be a custom data structure with additional information that can nonetheless be iterated over as if it were still an array. you simply write a for_expansion for the new data structure:<p><pre><code> Foo_Storage :: struct { items: [..] int; additional_info: string; } for_expansion :: (using storage: *Foo_Storage, body: Code, flags: For_Flags) #expand { for `it, `it_index: items { #insert body; } } foos: Foo_Storage; for foos { &#x2F;*...*&#x2F; } &#x2F;&#x2F; the loop interface remains unchanged </code></pre> I completely agree with the author here in that I appreciate this approach as opposed to Zig&#x27;s, with regards to making it as easy as possible to write basic constructs (&quot;loop over some stuff&quot;) that you&#x27;re going to be writing a lot, in a lot of different places, in a lot of different contexts, all the time, constantly. this is the one area in which this language and the design ethos behind it is completely different from Zig and other contemporaries—it balances power and simplicity with developer ergonomics quite nicely.
hermitsings超过 3 年前
Helpful article.
JediPig超过 3 年前
I get this feeling its a one &#x2F; two &#x2F; three man I want to write a compiler phase. I seen dozens of these languages over the years. I looked at the language, and without something revolutionary, this will die a slow death. I think it is experiencing that , main developer(s) are using crowd funding and nothing has really been &quot;wow&quot;.<p>I was right about dart and flutter being the next big one. However, zig is a dead language in a grave yard of 100s. It tries to revolution coding without changing the methodology.
评论 #29704915 未加载
评论 #29706224 未加载
评论 #29704725 未加载
评论 #29706479 未加载
评论 #29704339 未加载
评论 #29704218 未加载