[HN Gopher] Looking into Zig
       ___________________________________________________________________
        
       Looking into Zig
        
       Author : GordonS
       Score  : 229 points
       Date   : 2021-08-06 20:12 UTC (1 days ago)
        
 (HTM) web link (ayende.com)
 (TXT) w3m dump (ayende.com)
        
       | Groxx wrote:
       | Purely on the topic of `errdefer`, I believe the equivalent in Go
       | would be:                   // must use named returns so you can
       | observe the returned error         func yourfunc() (result
       | thingtype, err error) {           thing := constructIt()
       | defer func(){             if err != nil {
       | thing.Close()             }           }()                // use
       | thing to do a few things that could error           err =
       | thing.setup()           if err != nil {             return nil,
       | err           }           other, err := thing.other()
       | if err != nil {             return // naked returns are fine too
       | }           // etc                    return         }
       | 
       | Which is...... _technically possible_ , and not even all that bad
       | (as much as I strongly dislike named returns, since I find them
       | very error-prone), but the fact that I have not ever seen this
       | done does sorta reveal how much friction there is. Instead, I
       | usually see manual additions of err-cleanup to relevant branches,
       | and I've seen that pattern fail repeatedly as well (especially
       | when the code is modified much later by some other person).
       | 
       | The Zig equivalent seems like it would be roughly (I don't know
       | Zig)                   func yourfunc() thingtype {
       | thing := constructIt()           errdefer thing.Close()
       | // use thing to do a few things that could error           try
       | thing.setup()           other = try thing.other()
       | return thing         }
       | 
       | which is quite a bit more palatable and future-mistake-resistant.
       | A sizable chunk of that is due to `try` of course, but still.
        
         | mjbrusso wrote:
         | The equivalent in Visul Basic would be:
         | 
         | On Error Goto line
        
           | tored wrote:
           | Deserves an upvote. Not everyday you see praise about Visual
           | Basic.
           | 
           | Looked this up and _line_ can also be a label. Great.
        
           | benibela wrote:
           | Or in Pascal                  try          ...        except
           | end
           | 
           | wrapped around the error/exception generating code
        
         | ziml77 wrote:
         | I'd be interested to see if someone who works regularly with Go
         | can show a cleaner way to do this. Because what I'm seeing here
         | is just reinforcing my biases against Go. I've tried Go a
         | couple times before but only ever read about Zig and yet I
         | still find the Zig far easier to follow. It's much less verbose
         | without being less explicit.
         | 
         | (Also I'm not sure if the compiler would catch this, but there
         | seems to be a bug in that Go code that's hard to see at a
         | glance. You're never assigning a value to result)
        
         | slimsag wrote:
         | Actually, not only are you right about your errdefer Go
         | implementation - but that's actually fairly common in Go code.
         | 
         | Especially for tracing/logging of errors returned from
         | functions; or for e.g. rolling back DB transactions in the
         | event of an error.
         | 
         | Here's some ~100 examples from my work's (Sourcegraph's)
         | codebase[0]
         | 
         | [0]
         | https://sourcegraph.com/search?q=context:global+repo:%5Egith...
        
       | Zababa wrote:
       | > This year, I decided to look into Zig. Both Zig and Rust are
       | more or less in the same space, replacing C.
       | 
       | Maybe we should think about this in terms of space occupied by
       | the languages and not the language themselves. One of the
       | features of C is that pretty much anything can interface with it.
       | Another is that you can write very fast code with it. Another is
       | that pretty much any platform has a C compiler. Another is that
       | it's small and fits in your head. Depending on what you're trying
       | to do, you might use one "C replacement" or another.
       | 
       | Another way of looking at it would be to see the shortcomings of
       | C you're trying to overcome. I think this way of thinking would
       | be more productive than just thinking about "replacing C",
       | "replacing C++" or things like that.
        
         | mypalmike wrote:
         | I think there's an implicit, often unspoken list of C
         | shortcomings wherever these replacement languages are
         | concerned. Some of the most obvious ones are: Macro hell,
         | transitive include hell, and the ease with which even
         | experienced developers can unwittingly create unsafe code.
        
           | rightbyte wrote:
           | > Macro hell
           | 
           | I can hardly think of any language addon more innocent than
           | Cpp (the preprocessor).
           | 
           | Imagine what madness would have emerged if it had proper
           | variable assignment, goto:s or any loop construct?
        
         | xhealthgothx wrote:
         | Zig libraries can be exported with the C ABI[0], so pretty much
         | anything can interface with it. You can write very fast code
         | with it. It is also small and fits in your head. The only thing
         | missing is a variety of implementations, however there is a
         | clear path to bootstrapping the compiler from source with a
         | semi-recent C++ compiler[1] and from there, there's already a
         | growing number of supported targets[2]. There is also a major
         | focus on making sure cross-compilation is well supported out of
         | the box, including C code that Zig can also compile[3].
         | 
         | It's perfectly fair to compare Zig to C in this case, as the
         | project originated as a dialect of C before the author decided
         | to do a complete clean break[4]. The primary frame of reference
         | when designing the language was C and addressing its
         | shortcomings, both language and tooling.
         | 
         | [0]: https://ziglang.org/learn/overview/#export-functions-
         | variabl...
         | 
         | [1]: https://github.com/ziglang/zig-bootstrap
         | 
         | [2]: https://ziglang.org/download/0.8.0/release-
         | notes.html#Suppor...
         | 
         | [3]: https://andrewkelley.me/post/zig-cc-powerful-drop-in-
         | replace...
         | 
         | [4]: https://www.youtube.com/watch?v=Gv2I7qTux7g
        
           | Zababa wrote:
           | I'll restate my point: sometimes when replacing C people want
           | something that's just as fast but also way more safe, and in
           | that case will usually reach out for Rust. That's what the
           | people doing the cryptography in Python did. Rust can also
           | expose a C ABI, you can write code as fast as C. People will
           | often choose Rust instead of Zig because Rust has stronger
           | guarantees about memory safety, and these guarantees are more
           | important for them than having a language that's small and
           | fits in your head.
           | 
           | This is why I think talking about what you're trying to
           | achieve is more fruitful than just talking about the language
           | you want to replace. For example, if you want to replace C
           | code and you don't need all of the performance in the world,
           | you couold simply switch to a garbage collected language. In
           | that case, since speed wasn't the most important requirement,
           | a language that isn't usually thought as a C replacement can
           | replace C code.
           | 
           | If you want to make the point that Zig is "closer to C"
           | compared to other language that wants to replace C, that's a
           | fair claim to make.
        
             | Gibbon1 wrote:
             | I feel that people aren't using C because it's fast as much
             | as it's not dog slow. And that it has a stable ABI and a
             | very small footprint.
        
             | xhealthgothx wrote:
             | Rust is also not 'small and fits in your head', so that's
             | yet another point it is missing in your initial set of
             | criteria. Its main implementation and library also emits
             | rather large binaries in the usual case. You may not find
             | this important, but others do.
        
               | nicoburns wrote:
               | As others have pointed out, neither is C if you take into
               | account avoiding UB, the preprocessor, the build systems,
               | the many stdlib functions you need to avoid, etc. You
               | might already know how these work, but that doesn't mean
               | there's less to learn than a language like Rust.
        
               | Zababa wrote:
               | I addressed that point:
               | 
               | > People will often choose Rust instead of Zig because
               | Rust has stronger guarantees about memory safety, and
               | these guarantees are more important for them than having
               | a language that's small and fits in your head.
               | 
               | For some people, having a language that's small and fits
               | in your head is not a requirement, not a priority, and
               | sometimes not even important.
        
             | tialaramex wrote:
             | > This is why I think talking about what you're trying to
             | achieve is more fruitful than just talking about the
             | language you want to replace
             | 
             | This is definitely the right approach in my opinion. Even
             | for your garbage collection example on the one hand, in
             | some cases your program is dominated by tricky reclamation
             | problems and the "correct" Rust program is basically 90%
             | garbage collector, so that an existing GC language might
             | produce _faster_ programs; but on the far opposite scale
             | maybe your program has tricky non-memory resource problems
             | and GC doesn 't help at all, so the GC language has worse
             | performance and yet it makes your problem harder to solve
             | than in Rust anyway.
             | 
             | One of the nice things about Rust and about C++ RAII here
             | is that you don't care whether the resources are memory.
             | Database handles? Aerial drones? A tape robot? These are
             | all just resources you can wrap in an object to manage
             | them, in both languages. "I only have 15MB of RAM" and "I
             | only have 4 fire-fighting robots" are the same kind of
             | problem from this perspective.
             | 
             | > If you want to make the point that Zig is "closer to C"
             | compared to other language that wants to replace C, that's
             | a fair claim to make.
             | 
             | This is really important. Zig is very much inspired by C.
             | Rust has the syntax of a semi-colon language like C, but
             | its inspirations come from all over the shop. I came to
             | Rust having already programmed not only C and Java (and a
             | little C++) but also Python and ML (and a little Prolog)
             | and so this was less disconcerting. But I can see if you've
             | literally never encountered a functional language some of
             | Rust is _weird_ because even though it is spelled like
             | semi-colon languages you know it behaves very differently.
             | 
             | I like Rust, much more than I liked Go or Python when I
             | picked those up. It feels less clunky. An elegant weapon,
             | for a more civilised age.
        
               | Zababa wrote:
               | For the comparaison between C, Zig and Rust syntax, I'm
               | honestly not that sure. People love to complain about
               | Rust's syntax for reasons I don't really understand. Sure
               | the turbofish is a bit weird the first time, but other
               | than that I don't find it especially difficult. On the
               | other hand, I still have a hard time understanding Zig
               | code. Probably because I never really played with it, but
               | it's just like Rust, you need to familiarize yourself a
               | bit. Maybe people that did only C are able to get up to
               | speed with Zig more quickly than Rust? But that seems a
               | bit superficial, if these people are already spending
               | most of their time with only one language, if they learn
               | a second to spend that much time with a few hours to get
               | up to speed with the syntax is nothing.
        
         | oconnor663 wrote:
         | > Another is that it's small and fits in your head.
         | 
         | I know this is a common view, but I want to highlight some
         | counterexamples:
         | 
         | - C programmers need to learn about many different forms of UB:
         | https://blog.regehr.org/archives/1520. Most take years to learn
         | these rules. Many never learn them.
         | 
         | - Most real world C programs use some nonstandard language
         | extensions on some target platforms. C learners trying to read
         | production code have to navigate these.
         | 
         | - The C compilation and linking model is complicated and
         | platform dependent. Compilation is a major stumbling block for
         | students who have to learn Make or CMake at the same time they
         | learn C.
         | 
         | There is some truth to the "C is simple" idea, I'll grant that.
         | It's obviously simpler than C++. But I think there's a big
         | effect where we tend to forget how hard it was to learn,
         | because we learned it so long ago. There's also been
         | substantial progress since the 70's on designing simpler
         | programming languages.
        
           | surajs wrote:
           | A reduced feature/keyword set does not a simple language
           | make. C is smaller, but definitely not simpler. Also
           | definition of simplicity is context dependent, I would say in
           | many scenarios C++ turns out to be the simpler choice.
        
           | alerighi wrote:
           | C is not a difficult language. I know a lot of electronic
           | engineers that know how to program in C but don't know a
           | thing about informatics, for example what is DNS, or what is
           | JSON, or how to access a FTP server, and things like that.
           | But they know how to program their microcontrollers in C.
           | 
           | > C programmers need to learn about many different forms of
           | UB: https://blog.regehr.org/archives/1520. Most take years to
           | learn these rules. Many never learn them.
           | 
           | UB really don't care that much in real life. When you are
           | targeting a particular platform, that for most C programmer
           | is some sort of 8/32 bit microcontroller, the only thing you
           | care is the datasheet of the microcontroller. Of course you
           | do things that in general are undefined behavior, but in the
           | particular case lead to a perfectly predictable result.
           | 
           | In reality you only have to care about UB if your goal is to
           | share code between hardware platform. But let's be realistic,
           | most of the time you don't. Even if you do, some UB are these
           | days standardized, for example integer overflow is UB, in
           | practice you know that on every architecture 2 complement
           | arithmetic is used and thus is well defined.
           | 
           | The real problem is that compiler for a misinterpretation for
           | the standard started treating UB as "you are allowed to do
           | whatever stupid thing you want since the condition will never
           | happen", that is the real problem. In reality if you compile
           | without optimization and with flags that avoid this stupid
           | decisions it's not a problem.
           | 
           | > Most real world C programs use some nonstandard language
           | extensions on some target platforms. C learners trying to
           | read production code have to navigate these.
           | 
           | Again, it's a problem only if you are targeting different
           | hardware platforms. But if you only program on ST
           | microcontrollers (for example) why should you care?
           | 
           | And you must use them in some situations, for example in C
           | there is not a way to control how a struct is packed (to
           | decode efficiently data from a serial connection for example
           | you define a packed structure and access individual fields).
           | Or inline assembly is not in the standard (what if you need
           | to use an instruction of the microcontroller that is not
           | exposed by the C library?).
           | 
           | > The C compilation and linking model is complicated and
           | platform dependent. Compilation is a major stumbling block
           | for students who have to learn Make or CMake at the same time
           | they learn C.
           | 
           | It's. But most of the time you stuck on whatever the
           | development environment for the target hardware platform is
           | setup to. Most C programmers doesn't even know what CMake or
           | Make is, I care about it and do things by hand, most other
           | people use IAR or Keil or whatever proprietary software that
           | integrates compiler, build system and IDE.
        
             | jolux wrote:
             | Compilers _are_ allowed to do whatever they want when
             | encountering undefined behavior, not because it will never
             | happen, but specifically because it's undefined.
        
               | SAI_Peregrinus wrote:
               | And they're allowed to do whatever they want even with
               | optimizations off.
        
               | oconnor663 wrote:
               | And future versions of your compiler are going to want to
               | do different things with your UB than what your current
               | compiler does.
        
             | Zababa wrote:
             | I think your post highlights perfectly why I think we
             | should talk about the roles of C and not C itself. The C
             | you talk about seems to be a very different beast compared
             | to the C people write and use when building shared
             | libraries that are used across a wide variety of platforms.
             | For example, the people writing OpenSSL would have very
             | different concerns from the people you talk about.
        
             | tialaramex wrote:
             | > In reality if you compile without optimization and with
             | flags that avoid this stupid decisions it's not a problem.
             | 
             | Worse programs. Written by people who believe "C is not a
             | difficult language" and who sacrificed all benefits of
             | using a high performance language because they couldn't
             | understand what they were doing.
             | 
             | So long as you don't have any competitors who use a better
             | language or skilled programmers you can coast along like
             | this, putting out a sub-par product and just pretending
             | it's the best possible. But you can get a very sudden and
             | rude awakening if anybody decide to offer what's possible
             | here.
        
             | pjmlp wrote:
             | Easy one uses an external Assembler like in the good old
             | days when inline Assembly wasn't a feature one could rely
             | on.
        
           | alfiedotwtf wrote:
           | Thanks! This is probably the first time I've heard C called
           | _not_ a small language.
           | 
           | Perl was my main language for over a decade, and when I
           | wanted to go lower, I honestly struggled... but not with the
           | language itself, with the peripherals which are exactly what
           | you described!
        
             | SAI_Peregrinus wrote:
             | C is small, but it's not simple or easy to get right.
        
               | pjmlp wrote:
               | Depends on how much compiler extensions across multiple
               | compilers one wants to be knowledgeable on.
        
           | Zababa wrote:
           | That's a good point. I personally don't share this view, and
           | it's also not something I look for in a language. But people
           | using C currently seem to be very attached to this, and
           | knowing how to connect to your audiance is important.
        
         | oddity wrote:
         | Absolutely! A common example I like to use is Java. It might be
         | hard to imagine now, but there was a time where Java (and then
         | C#) were pitched as a replacements to C++ (even the name "C#"
         | supposedly derived from "C++++"). There was no reason to write
         | native code any more, many people said. And, they were kind of
         | right. Many people were writing applications in C++ because
         | they thought they had to, even though they weren't writing C++
         | in the style needed to make proper use of it. A lot of old C++
         | code bases today look like much more verbose Java applets. This
         | peeling, when it happens, is usually good for everyone since
         | languages (and tools) evolve to better fit the domains in which
         | they are most used and happens so gradually that few notice.
         | The inverse also happens, but with more conflict: you can see
         | this today in Python (and other dynamic languages) adopting
         | typing features aimed at assisting tooling for large code
         | bases, well beyond the traditional learning or glue scripting
         | mentality for which they were designed. This often results
         | fierce debates around language features (like static typing vs
         | dynamic typing) that are really proxy battles for the usage
         | intent of the language.
         | 
         | Unfortunately, I think the "replacing X language" mentality
         | happens because it's the easiest point to start with. The field
         | of programming and computers is so vast now that most (all?)
         | people have a very narrow view and it's easy to assume it's
         | universal. I've lost track of all the "things all programmers
         | should read/know/do" articles.
        
           | hawski wrote:
           | Many C++ code bases, especially older ones, I have seen were
           | really trying to be their own Java. This caused them to join
           | disadvantages of C++ with disadvantages of Java. I don't
           | believe the result was faster than JVM and start up time
           | hardly mattered and still was not fast enough.
        
             | jcelerier wrote:
             | I dont't think the slowest c++ app I ever used was slower
             | than the fastest java app I ever used
        
               | pjmlp wrote:
               | Even when it wins the benchmark games, it isn't relevant
               | for many businesses.
               | 
               | There is a budget to be fulfilled for project delivery
               | acceptance, going beyond that is wasted money.
        
           | Zababa wrote:
           | > Unfortunately, I think the "replacing X language" mentality
           | happens because it's the easiest point to start with. The
           | field of programming and computers is so vast now that most
           | (all?) people have a very narrow view and assume it's
           | universal. I've lost track of all the "things all programmers
           | should read/know/do" articles.
           | 
           | I think another effect is that if you really like a language,
           | promoting it is one of the best thing you can do to work with
           | it. When you see the recent (2010 and later) new languages,
           | they all have a story of addressing a particular pain point.
           | Typescript is Javascript at scale, Kotlin is old Java on
           | android, Go is web services, Rust is performance and safety.
           | This is solid marketing, and is part of how these languages
           | end up dominating their domains. On the other hand, a
           | language that's "X but slighly better everywhere" won't
           | really attract people, since there is already code and jobs
           | in that language.
           | 
           | Currently in the Great War Of Replacing C And C++, there are
           | lots of fighters. Some people promote Rust, some others Go,
           | some others D, some others Zig, some others to just keep
           | writing C and C++. Part of the battle is writing code,
           | libraries. Part of the battle is making the language and
           | tooling itself better. And part of the battle is making
           | articles, comments, talking to people and promote your
           | language.
        
             | pjmlp wrote:
             | The best way to win battles in the context of systems
             | programming languages is to have a platform ship with the
             | language, libraries alone won't do it.
             | 
             | This is how C put other of business other system languages,
             | much better than it. When you get UNIX and have already
             | paid for a compiler, hardly any department will allow to
             | buy additional compilers.
             | 
             | And C++, people tend to forget it was also born on the same
             | place as UNIX and C, thus it was quickly adopted by all
             | OSes that were UNIX clones in some fashion, and then by C
             | compiler vendors on other platforms.
             | 
             | And on cases like Java, Go, TypeScript or Kotlin, you need
             | a godfather company to push it no matter what.
        
               | Zababa wrote:
               | For the part about platforms, hasn't that ship already
               | sailed? From what I understand the industry had settled
               | on C, C++, Windows and UNIX. Some people are trying to
               | replace some of these with different solutions, but
               | that's about it. I think a new platform would have the
               | same challenges as a new system programming language, but
               | would be even harder to convert people to.
        
               | pjmlp wrote:
               | Not at all.
               | 
               | Want to develop for Apple platform?
               | 
               | Depending on which level of the stack, the painless
               | option will be C++, Objective-C or Swift.
               | 
               | On Android it will be a mix of Java (slowly being left
               | behind on purpose), Kotlin or C++.
               | 
               | On Windows, .NET (and in some cases C# or C++/CLI only
               | due to the way MSIL gets exposed) and C++. You can also
               | keep using C if your view of Windows is like Windows XP
               | APIs.
               | 
               | On Fuchsia, it is all about Flutter, C++, Go and Rust.
               | 
               | On ARM Mbed and Arduino, C++.
               | 
               | On microEJ, Java and C.
               | 
               | On Meadow, .NET.Core.
               | 
               | Azure Sphere, C.
               | 
               | CUDA, C++, Fortran, Python JIT and PTX aware backends.
               | 
               | There are plenty of other platforms I could keep on
               | listing.
               | 
               | Naturally you can try to fit something else, but then it
               | is on you and others to build the ecosystem, work around
               | support issues and lack of IDE tooling.
        
               | Zababa wrote:
               | I see, I had a really limited vision and understanding of
               | what you meant by "platform". That makes a lot of sense.
               | Thanks.
        
         | 0-_-0 wrote:
         | Nim compiles to C, so it can be a drop in replacement.
        
           | Zababa wrote:
           | I think you should be a bit more precise on exactly when. If
           | it compiles to C, that means that it inherits from C the
           | great platform support. I don't know much about it, so I
           | can't judge Nim on other qualities that people attribute to
           | C: you can call it from pretty much any language, it's seen
           | as simple, you can write highly performant code in it, you
           | can use it in very restricted environments, and I'm probably
           | forgetting some others.
        
             | jasfi wrote:
             | It's also very easy to write Nim, the syntax has been
             | compared to Python.
        
               | Zababa wrote:
               | Honestly, I don't think these kind of drive-by shallow
               | comments are selling anyone on Nim. Many people here have
               | posted long and insightful comments about the
               | complexities of replacing C and some other topics, and
               | two of the three comments about Nim are a bit shallow.
        
         | auxym wrote:
         | I think the fact that Nim compiles to C is neat in that you can
         | use it on any platform that has a C compiler.
         | 
         | Here is a recent project that uses nim for AVR platforms, for
         | example: https://github.com/PMunch/badger
        
       | agbell wrote:
       | I know very little Zig, but I agree with the post, that comptime
       | seems simple, obvious and powerful.
       | 
       | It is interesting that it bears some surface level similarities
       | to type constructors in languages with higher kinded types.
        
         | naasking wrote:
         | Yes, and in principle you can generalize the type language into
         | a full language with lambdas and such (type constructor is a
         | lambda(ground type)->ground type), though you typically want it
         | to be strongly normalizing so you know that the compiler will
         | eventually halt. Then you don't need kinds, kind polymorphism,
         | sorts, etc., you just have a dependently typed language with
         | types and universes.
        
           | agbell wrote:
           | Yeah, functions returning types based on computations in Zig
           | can look a lot like Idris if you squint
        
       | koeng wrote:
       | One thing that I'm quite bummed out with Zig is the lack of a
       | good http server/client implementation in the standard library.
       | Golang's std implementation on this is really quite nice.
        
         | [deleted]
        
         | kubb wrote:
         | Yes, a large team of highly paid engineers at Google produced
         | better libraries than that one guy working on Zig as a passion
         | project.
         | 
         | And yet that one guy still managed to build in useful features
         | to his language that the Google "geniuses" couldn't think of
         | despite (or because?) decades of experience.
        
         | young_unixer wrote:
         | In my opinion, that's outside the scope of a general-purpose
         | programming language.
        
           | moogly wrote:
           | A client, at least, will be needed in the standard library
           | for their upcoming package manager.
        
         | throwaway17_17 wrote:
         | Do you feel like http server/client is 'mandatory' in a
         | standard library in 2021? I don't really do any web adjacent
         | programming so it's not something I ever think about. However,
         | I know I am in a very small group of people who don't have to
         | worry about web stuff. I've been toying with a release of the
         | personal language I use and was just rolling around the idea of
         | what to put in the 'standard' library if I do release it.
         | Anything else you think has to be in a std library?
        
           | lostcolony wrote:
           | It's very much a nice to have for a new language nowadays, as
           | even if web dev isn't the key niche of the language, any
           | success the language has is likely to still include a need
           | for it. Adding it also creates interfaces and conventions
           | that any third party ones can choose to adopt, to ensure it's
           | a drop in replacement (and even if they don't fully, they'll
           | likely still follow the same paradigm). This is really
           | beneficial as, while the stdlib's version may be very
           | middling, it ensures adopting the language and a third
           | party's http implementation isn't going to trap you into
           | something that becomes unmaintained, and which doesn't have a
           | clean migration path away from; you can always fall back to
           | using the stdlib's http library, since there's an expectation
           | it will be maintained along with the language.
           | 
           | That said, if you're putting your language up as a "see the
           | neat thing I did that's helpful in this very specific
           | domain", and not general purpose, with the intent of
           | supporting, it's probably immaterial to you.
        
             | chakkepolja wrote:
             | I don't think zig is aiming in that category. I see it as a
             | system language.
             | 
             | Although these days people want to apply their favorite
             | language to everything, I don't think zig will be a main
             | language for writing web backends or http services. it's
             | place is game engines, computer graphics, kernels, drivers
             | etc..
        
             | dnautics wrote:
             | To some degree if you really needed the client, it would be
             | almost trivial to import libcurl "as it is" into zig.
        
             | throwaway17_17 wrote:
             | It's less a specific domain thing and more an overly
             | opinionated exploration framework for me. Not that it's
             | really important, but the language is a modal dependent
             | type theory with a compositional (even though most people
             | would call it concatenative) syntax that compiles to C,
             | C++, and JavaScript. So I can always just reuse the
             | underlying platform http and the rest of the stdlib.
        
           | naasking wrote:
           | > Do you feel like http server/client is 'mandatory' in a
           | standard library in 2021?
           | 
           | A server isn't necessary, but 100% yes for a client. There's
           | a lot of eating your own dog food needed for an http client,
           | like string handling with encodings, network bindings,
           | various collection types, async I/O and/or binary streams,
           | error handling. The resulting client showcases the strengths
           | of the language and its standard library, and most data is on
           | the web today.
        
             | c-cube wrote:
             | High level bindings to cURL would be better imo. You don't
             | reinvent this tricky wheel, and you get a lot of features
             | (even async I think?) on top of a strong implementation.
             | And a http server really doesn't belong in the stdlib of a
             | system language.
        
           | koeng wrote:
           | Basic string manipulation, JSON encoding, file
           | reading/writing, some type of hashing/checksum, and an HTTP
           | client/server. Those things I've really appreciated about Go
           | lately as I get it to control robots (controlling them over a
           | REST api on local network writing commands to a serial port).
        
         | jks wrote:
         | They're discussing this in
         | https://github.com/ziglang/zig/issues/910 (server) and
         | https://github.com/ziglang/zig/issues/2007 (client).
        
       | tored wrote:
       | Great article. I mostly do PHP, PHP has support for FFI and I
       | have some private projects where I call C libraries directly over
       | FFI. I have been thinking of using zig to implement my own C
       | libraries when needed. Zig looks like a more sane approach than
       | using C, another alternative would be D.
        
       | danielparks wrote:
       | He posted a follow up about error handling in Zig that I thought
       | was interesting: https://ayende.com/blog/194466-A/looking-into-
       | odin-and-zig-m...
       | 
       | I've seen the "clean up errors yourself" argument before, but,
       | like the author, I don't think it holds water. Often the correct
       | response to errors is to panic() or pass it up the stack so the
       | caller can deal with it or--more likely--panic() itself.
        
         | tored wrote:
         | I agree with the author that _errdefer_ seems like the winning
         | feature of zig. Proper error handling is the most important
         | part of any language or system.
         | 
         | Unfortunately most common languages does not prioritize this.
         | As a contractor I have dug myself thru a lot of awful code in
         | different languages and the most common denominator is improper
         | error handling.
        
         | Zababa wrote:
         | I think it's nice to have two mechanisms for errors like in ML:
         | sum types for errors that the calling function can
         | realistically recover from, and exceptions for the rest.
        
           | Gaelan wrote:
           | This is Rust's approach, too: realistically recoverable
           | errors are handled with Result<T, E>, and other are handled
           | through panics. (Panics are generally implemented as
           | exceptions, i.e. they unwind the stack, but the compiler can
           | also be configured to make them just abort.)
        
           | dnautics wrote:
           | You can do that in zig with @panic and even convert from sum
           | type error to an irrecoverable exception: `catch
           | @panic("oops");`
        
             | Zababa wrote:
             | That's nice. Are the sum types checked by the compiler to
             | ensure that you didn't miss any case?
        
               | squeek502 wrote:
               | If I understand you correctly, then yes.
               | fn canError(foo: bool) !void {             if (foo) {
               | return error.Foo;             } else {
               | return error.Bar;             }         }
               | test "canError" {             canError(true) catch |e|
               | switch (e) {                 error.Foo => @panic("foo!"),
               | };         }
               | 
               | Running `zig test` on that file would give:
               | ./tmp/errors.zig:10:30: error: error.Bar not handled in
               | switch             canError(true) catch |e| switch (e) {
               | ^
        
               | Zababa wrote:
               | You did understand it correctly. That's a really nice
               | feature.
        
               | AndyKelley wrote:
               | Yes, and you can even handle some errors, and then
               | capture an error whose type is the subset of unhandled
               | errors, and return that, limiting the error set of the
               | current function to not include the handled ones. Here
               | are a couple examples: https://github.com/ziglang/zig/blo
               | b/7d0de54ad44832589379a4bc...
               | 
               | You get compile errors if you try to handle an impossible
               | error, or don't include an `else` prong (in which case
               | the compiler tells you the full set of unhandled errors).
        
               | Zababa wrote:
               | That's a great feature. I'm constantly impressed by what
               | Zig can do.
        
         | ksec wrote:
         | Off Topic:
         | 
         | >He posted a follow up about error handling......
         | 
         | When I was reading the original blog I was thinking if he had
         | any follow up, so I decide to click on archive and the
         | homepage. And this article, somehow doesn't show up in both
         | list. As a matter of fact I couldn't even find how to get to
         | this blog post without your direct linking. Then it turns out
         | it is a "FUTURE POSTS".
         | 
         | How does that work and why? Is this suppose to be some sort of
         | preview before it is officially published?
        
           | danielparks wrote:
           | Yeah, it's weird. I tried stripping the key= parameter from
           | the link when I commented, but it's required.
           | 
           | The author posted the link in the comments of the original
           | post.
        
       | yakubin wrote:
       | Zig looks overall interesting to me, but I don't like that it
       | reproduces one of the pains of C++ templates, i.e. their dynamic
       | typing. What I mean is, C++ templates aren't checked before being
       | executed, and instead you get compilation errors (at c++
       | templates runtime) which mangle the use and definition of
       | templates, e.g.                 template<typename T>
       | concept HasId =       requires (T a) {           T::kId; // "the
       | expression T::kId is a valid expression that will compile"
       | };            // A and B are expected to be structs, where each
       | has an associated integer constant kId and a field "int value".
       | template <HasId A, HasId B>       int min_id(const A a, const B
       | b) {         if (A::kId < B::kIs) {             return a.value;
       | } else {             return b.value;         }       }
       | struct A0 {         static constexpr int kId = 1;         int
       | value;       };            struct A1 {         static constexpr
       | int kId = 2;         int value;       };            // etc.
       | struct A180 {         static constexpr int kId = 2;         int
       | value;       };            int main() {
       | (void)min_id(A0(), A1());           (void)min_id(A1(), A2());
       | // etc. ending with:           (void)min_id(A179(), A180());
       | }
       | 
       | And now you get 180 errors about your typo (if not for max error
       | number limits in the compiler), when really there is only one
       | error in the definition of min_id. I used concepts to show that
       | in the long tradition of C++, they're an additional feature that
       | doesn't really help (quantity over quality of features).
       | 
       | Haskell solves that with typeclasses, Rust solves that with
       | traits. What's really important about these solutions is that
       | when you write a function generic over a trait or a typeclass,
       | you are limited to using what is defined in the trait/typeclass.
       | The trait/typeclass function both as documentation and as
       | something that gets you better compilation errors.
       | 
       | "typename" in C++ is basically "any", but for values of template
       | execution. Typeclasses/traits on the other hand are a sort of
       | types for those values (which we normally call "types"). And
       | similarly, in Zig there is an "any" type for types, just like in
       | C++ --- it's called "type", and AFAIK there is no way to
       | constrain your types with types of types.
        
         | chakkepolja wrote:
         | Is the problem about C++ templates it's error messages or not
         | being able to strictly type the arguments in type signature?
         | 
         | I have a question to the compiler / IDE people here. In case of
         | C++ templates, is it possible to output one error like: eg
         | "class UserData needs to implement operator< to be used in
         | min() function" instead of 200 lines errors? I mean, complex
         | cases it's not possible but at least for simple ones like using
         | an iterator variable directly instead of dereferencing it?
        
           | yakubin wrote:
           | Those two are connected. Without strict typing the compiler
           | doesn't know really whether the error is in the definition of
           | min() or in its use, so the compiler mangles the two together
           | and lets the programmer figure it out.
           | 
           |  _> In case of C++ templates, is it possible to output one
           | error like: eg  "class UserData needs to implement operator<
           | to be used in min() function" instead of 200 lines errors?_
           | 
           | This is already handled by concepts, but concepts solve only
           | half the problem. E.g. in my snippet, in the comment you
           | replied to, if any of the structs didn't have the kId
           | constant, the errors would be about that. Concepts correctly
           | detect when someone passes to them things that don't
           | implement required functionality (as long as this
           | functionality is specified in the concept). The other half of
           | the problem, which they do not solve, is checking the
           | correctness of the definition of the template against the
           | concept. E.g. in my snippet I could use the "value" field,
           | even though the concept that I used didn't declare it
           | anywhere. At that point, if I passed a struct, which doesn't
           | have that field, the compiler wouldn't be able to tell where
           | the error is: in the template, or in its use --- so it would
           | emit one error for each template instantiation, just as it
           | did for "kIs" (because it can't know that it's just one typo
           | in one place).
        
             | chakkepolja wrote:
             | I was asking about the no-concept case.
             | 
             | I was thinking something like this:
             | 
             | Compiler encounters operator<(T) on argument (type T) is
             | called.
             | 
             | In best case it sees it was a function parameter. In worst
             | case it at least sees concrete type of the parameter. Let's
             | say that type is UserData
             | 
             | It will say that UserData type needs to implement
             | UserData::operator<(UserData) to be able to use min()
             | function.
             | 
             | Of course I can see this getting complex as nesting etc..
             | increase. But I am wondering if clang (since it's selling
             | points include error messages, though gcc is catching up),
             | hasn't tried something like this, there must be a
             | fundamental technical difficulty for generalizing such a
             | technique.
        
             | tialaramex wrote:
             | > Concepts correctly detect when someone passes to them
             | things that don't implement required functionality
             | 
             | Unfortunately C++ Concepts check _syntax_ even though as
             | you 'd expect the intention of the feature is to reflect
             | _semantics_ there is deliberately no way to capture that.
             | 
             | So e.g. Rust has traits PartialEq and Eq reflecting things
             | that claim to be partial or full equivalence relations.
             | There's no syntactic difference, a Rust type can't
             | _syntactically_ be impossible to check for equivalence with
             | some values and not others but e.g. Rust 's f32 implements
             | PartialEq not Eq due to NaNs whereas u16 has both since
             | integers all exhibit equivalence.
             | 
             | But in C++ there's just std::equality_comparable and it
             | matches both integers and floats _even though NaNs aren 't
             | in fact comparable_ because the float type syntactically
             | has the == operator.
             | 
             | So this means in C++ concepts matching means your program
             | _compiles_ but it might blow up at runtime thanks to a
             | difference in functionality rather than syntax.
             | 
             | To C++ programmers this is positioned as yet further
             | responsibility on their shoulders. They must check that the
             | data they're using _actually_ models the concept that was
             | required, it 's not anybody else's job and if they get it
             | wrong the program blows up.
        
               | aseipp wrote:
               | I mean, I feel this particular example is really more of
               | standard library design wart that occurs with any kind of
               | syntactic overloading mechanism, e.g. Haskell has the
               | exact same problem as C++ does here even though the
               | overloading mechanism is rather different (Eq is defined
               | for Float and there is no notion of a PartialEq in the
               | standard library, even though there really should be),
               | and there are numerous more advanced examples of that
               | (every few years someone writes a fun library that
               | violates the Monad laws, for instance). The fundamental
               | question is: does an instance of an overloading mechanism
               | respect the "properties" you expect of it, algebraic ones
               | or not? Your program will often behave weirdly if the
               | answer is "no" but the extent of the weirdness
               | permissible is a spectrum. Basically no languages
               | actually allow you to validate those semantics; it's
               | expected that the "validity" of those instances is proven
               | or known _a priori_ , and bad ones don't exist.
               | 
               | IMO, the bigger problem with this particular example is
               | just that the numeric and algebraic hierarchies in most
               | languages are littered with various edge cases just like
               | this one, and that makes it an easy and convenient
               | nitpick to point out. But I think the parent comment is
               | largely correct in that the goal of a concept (or trait,
               | or typeclass) is roughly to reflect a property or action
               | of some object or type or what have you, even if C++
               | wasn't as originally as forward thinking as other
               | languages today are with invariant safety.
        
               | tialaramex wrote:
               | The practical difference between C++ Concepts and Rust
               | Traits is that Rust Traits get to have semantics _by
               | declaration_ and you can 't do that with C++ Concepts.
               | 
               | A Rust type gets to choose whether to be Eq or just
               | PartialEq. I can wrap floats up in a new type, MyFloat,
               | provide an implementation of == to qualify it as
               | PartialEq and then I can choose whether to just _declare_
               | that it 's Eq. The _compiler_ cannot check I told the
               | truth, but as implementer I can decide whether to promise
               | that or not.
               | 
               | In C++ you do not get a choice. C++ concepts refer to
               | syntax and _only_ that. I can write a concept named
               | hates_balloons and have it depend on types implementing a
               | zero argument method named  "pop". But if your stack
               | class with a pop method doesn't in fact hate balloons too
               | bad, my concept says that since the syntax matches you
               | have no choice, your stack hates_balloons and there is
               | nothing you can do about it.
               | 
               | I understand exactly why C++ did this. There is a _lot_
               | of legacy C++ code out there. If you make every _new_ C++
               | iterator say it implements the iterator concept and don
               | 't grandfather the existing ones, nobody uses the
               | feature. But, even though they had a good reason to do
               | this, it's still a considerable weakness.
        
       | pharrington wrote:
       | I completely do not understand why the author thinks Rust is a C
       | replacement. I can understand Rust as a C++ replacement.
       | 
       | If he was looking for a better C, Zig definitely fits the bill.
        
         | masklinn wrote:
         | Rust is a C replacement not in the "tactical" sense of "I like
         | C but it's a bit shit", it's a C replacement in the "strategic"
         | sense: it aims to displace C in most of its core usages e.g.
         | writing low-level or portable libraries, CLI utilities,
         | daemons, kernel and kernel modules, etc... places where only C
         | (and C++ somewhat more debatably) would be an option and
         | continuously causes issues.
         | 
         | It _also_ aims to displace C++ when that 's used in the same
         | space, but in the sense that that's ground C++ gained from C,
         | well C is the real target, if it can displace C there it can
         | quite naturally displace C++ as well.
        
         | richardanaya wrote:
         | Probably has something to do with Rust being used in embedded
         | and kernel operating systems due to it's high level of memory
         | control and zero runtime capabilities.
        
         | Zababa wrote:
         | Rust is already used as a C replacement in some cases. However,
         | as I said (https://news.ycombinator.com/item?id=28094998), just
         | talking about a C replacement without mentionning why you were
         | using C in the first place and what you value in a replacement
         | isn't really productive.
        
         | pjmlp wrote:
         | Rust needs decades to catch up with domains that C++ has
         | managed to keep for itself, like GPGPU, GUI composition
         | engines, machine learning, HPC.
         | 
         | The other domains where C++ was strong for general purpose
         | applications have been taken over by managed compiled languages
         | like Java and .NET, which anyway make use of C++ libraries
         | alongside their AOT/JIT compiled stacks.
         | 
         | There is little value to add from Rust in such scenarios, e.g.
         | it won't make my WinUI application, CUDA shader or weather
         | simulation model, any more safer than they already are.
        
           | andi999 wrote:
           | C++ for gpgpu was more of an afterthought in nvcc, wasn't it.
           | I would be surprised if not most cuda kernels are written in
           | plain C.
        
             | pjmlp wrote:
             | Not at all, it was one of the reasons why OpenCL lost, by
             | staying too long focused on C.
             | 
             | CUDA supports C++ since version 3.0, and NVidia designs the
             | cards to follow C++ semantics, regardless of the polyglot
             | capabilities from PTX.
             | 
             | Hardly an afterthought, it was Khronos that became
             | surprised that most researchers don't want to use plain old
             | C on their research efforts.
        
               | andi999 wrote:
               | Good to know. Do you have further reading material on
               | this?
        
               | pjmlp wrote:
               | Sure,
               | 
               | "CppCon 2016: "Bringing Clang and C++ to GPUs: An Open-
               | Source, CUDA-Compatible GPU C++ Compiler"
               | 
               | https://www.youtube.com/watch?v=KHa-OSrZPGo
               | 
               | "CppCon 2019: Olivier Giroux "The One-Decade Task:
               | Putting std::atomic in CUDA.""
               | 
               | https://www.youtube.com/watch?v=VogqOscJYvk
               | 
               | "Octane render. The Future of GPU Rendering: Real-Time
               | Raytracing" (with CUDA)
               | 
               | https://www.youtube.com/watch?v=wGTIGjgXs6M
               | 
               | NVIDIA HPC SDK
               | 
               | https://developer.nvidia.com/hpc-sdk
        
       | richardanaya wrote:
       | Every time I read about Zig, I feel like I see a nice language
       | that's only an incremental improvement to C mostly in terms of
       | ergonomics. It's hard for me to imagine people giving up C for
       | only incremental gain.
        
         | sharikone wrote:
         | You could argue the opposite and say that because it is
         | incremental and easy to mix with C, it will be more easily
         | used.
         | 
         | When I program on my own I often write an idea in C and then
         | convert it to C++ when complexity rises, precisely because C++,
         | in terms of syntax, is an incremental update to C. Using say
         | Rust would entail a more serious rewrite.
         | 
         | Unfortunately Zig and Rust are quite different in syntax. I
         | would love to change my workflow from C->C++ to Zig->Rust but
         | the transition is not as nice.
        
         | flohofwoe wrote:
         | I thought that too in the beginning, but the comptime features,
         | type reflection and error handling really go beyond C, while
         | still being a simple and elegant language (in a way even
         | simpler than C). Also Zig is a nicer C/C++/ObjC toolchain than
         | most C/C++ toolchains (because of simple cross-compilation and
         | integrated build system).
        
         | naasking wrote:
         | Compile type computations, trivial cross-platform building and
         | linking, vastly better error handling, and more. Honestly, I'm
         | having a hard time seeing how these are only "incremental"
         | improvements over C.
        
         | defen wrote:
         | An alternative perspective is that you don't have to give up C
         | to use Zig - they are extraordinarily easy to mix together in
         | one project. So you can incrementally move an existing project
         | to Zig without rewriting the world.
        
       | sintezcs wrote:
       | I highly recommend the last episode of the "Corecursive" podcast.
       | The guest of the episode is Zig creator - Andrew Kelly, and he
       | tells about the history of Zig, it's really interesting!
       | https://corecursive.com/067-zig-with-andrew-kelley/
        
       | ngrilly wrote:
       | I really like Zig, but it's difficult to compare it with Rust
       | without mentioning Rust memory safety and data race freedom.
        
         | philprx wrote:
         | Thanks a lot, TIL this about zig:
         | 
         | https://scattered-thoughts.net/writing/how-safe-is-zig/
        
       | pjmlp wrote:
       | I have three main issues with Zig:
       | 
       | - @ everywhere, for that I would keep using Objective-C
       | 
       | - Compiled languages shouldn't be using text file imports as
       | modules
       | 
       | - I already have C and C++ for use after free/move errors
       | 
       | Free to disagree, it just means I am not part of the target
       | audience.
        
         | defen wrote:
         | > - Compiled languages shouldn't be using text file imports as
         | modules
         | 
         | Zig doesn't use C-style textual includes, if that's what you
         | mean.
        
           | pjmlp wrote:
           | Sure it does, @import expects a text file that is then parsed
           | into a struct like data structure.
           | 
           | I expect a proper binary module, with native code and symbol
           | table.
        
             | flohofwoe wrote:
             | The important part is that (unlike C/C++ headers) included
             | modules can't be polluted with code that's coming before
             | the @import(). Everything else is just an implementation
             | detail.
             | 
             | @import also has a second mode where the string isn't a Zig
             | source file path, but a package name. AFAIK currently this
             | also just resolves to a package-root zig file, but it could
             | just as well be extended to some sort of binary format, the
             | question is just: why?
        
               | pjmlp wrote:
               | Because many business situations we only want to
               | distribute binary libraries.
               | 
               | If I want to distribute source code I would be using
               | scripting languages.
               | 
               | It is also a nagging point for me when I play around with
               | cargo, which contrary to conan and vcpkg, doesn't do
               | binary libraries.
               | 
               | By the way, C++ modules might get a binary format
               | definition by C++26 (too little time to sort it out by
               | C++23), based on BMI/IFC formats already being deployed
               | in GCC and VC++ respectively.
        
         | papaf wrote:
         | _@ everywhere, for that I would keep using Objective-C_
         | 
         | If you are triggered by the AT character, I recommend that you
         | stay away from Slack and Microsoft Teams.
        
           | pjmlp wrote:
           | I really try hard to, but there are these things called job
           | and customers.
        
       ___________________________________________________________________
       (page generated 2021-08-07 23:02 UTC)