Live data from Hacker News

Zig; what I think after months of using it

strongly-typed-thoughts.net

11–20 of 181 posts

Re: Zig; what I think after months of using it

#12
No idea how much the author is experienced at Zig, but my thoughts:

> No typeclasses / traits

This is purposeful. Zig is not trying to be some OOP/Haskell replacement. C doesn't have traits/typeclasses either. Zig prefers explicitness over implicit hacks, and typeclasses/traits are, internally, virtual classes with a vtable pointer. Zig just exposes this to you.

> No encapsulation

This appears to be more a documentation issue than anything else. Zig does have significant issues in that area, but this is to be expected in a language that hasn't even hit 1.0.

> No destructors

Uh... What? Zig does have destructors, in a way. It's called defer and errordefer. Again, it just makes you do it explicitly and doesn't hide it from you.

> No (unicode) strings

People seem to want features like this a lot -- some kind of string type. The problem is that there is no actual "string" type in a computer. It's just bytes. Furthermore, if you have a "Unicode string" type or just a "string" type, how do you define a character? Is it a single codepoint? Is it the number of codepoints that make up a character as per the Unicode standard (and if so, how would you even figure that out)? For example, take a multi-codepoint emoji. In pretty much every "Unicode string" library/language type I've seen, each individual codepoint is a "character". Which means that if you come across a multi-codepoint emoji, those "characters" will just be the individual codepoints that comprise the emoji, not the emoji as a whole. Zig avoids this problem by just... Not having a string type, because we don't live in the age of ASCII anymore, we live in a Unicode world. And Unicode is unsurprisingly extremely complicated. The author tries to argue that just iterating over byes leads to data corruption and such, but I would argue that having a Unicode string type, separate from all other types, designed to iterate over some nebulous "character" type, would just introduce all kinds of other problems that, I think, many would agree should NOT be the responsibility of the language. I've heard this criticism from many others who are new to zig, and although I understand the reasoning behind it, the reasoning behind just avoiding the problem entirely is also very sensible in my mind. Primarily because if Zig did have a full Unicode string and some "character" type, now it'd be on the standard library devs to not only define what a "character" is, and then we risk having something like the C++ Unicode situation where you have a char32_t type, but the standard library isn't equipped to handle that type, and then you run into "Oh this encoding is broken" and on and on and on it goes.

Re: Zig; what I think after months of using it

#13
post #6

I loved this deep-dive of zig. > There’s a catch, though. Unlike Rust, ErrorType is global to your whole program, and is nominally typed. What does "global to your whole program" mean? I'd expect types to be available to the whole compilation unit. I'm also weirded out by the fact that zig has a distinct error type. Why? Why not represent errors as normal records?

> What does "global to your whole program" mean? I'd expect types to be available to the whole compilation unit. I think they mean you only have one global/shared ErrorType . You can't write the type of function that may yeet one particular, specific type of error but not any other types of error.

They're really just enum variants. You can easily capture the error and conditionally handle it:

fn failFn() error{Oops}!i32 { try failingFunction(); return 12; }

test "try" { const v = failFn() catch |err| { try expect(err == error.Oops); return; }; try expect(v == 12); // is never reached }

Re: Zig; what I think after months of using it

#14
post #4

Earlier quoted context omitted.

I'm not speaking for Zig, but in principle errors are not values, and often have different control flow and sometimes even data flow constraints.

Can you elaborate more?

They're enums. See: https://zig.guide/language-basics/errors

Re: Zig; what I think after months of using it

#15
post #7

When did shadowing become a feature? I was under the impression it's an anti-pattern. As per the example in the article > const foo = Foo.init(); > const foo2 = try foo.addFeatureA(); > const foo3 = try foo.addFeatureB(); It's a non issue to name vars in a descriptive way referring to the features initial_foo for example and then foo_feature_a. Or name them based on what they don't have and then name it foo. In the e…

Shadowing always has been a feature, doubly so in languages which lack linear types. It is a promise to the reader (and compiler) that I will have no need of the old value again. Notice that applying the naming convention you suggest does nothing to prevent the bug in the code you quoted. It might be just as easy to write const initial_foo = Foo.init(); > const foo_feature_A = try initial_foo.addFeatureA(); > const f…

Said promise should also be checked for sanity. E.g.

  for i in range(N) {
    for i in range(M) {
      # Typo; wanted j.
      # The compiler should complain.
    }
  }

Re: Zig; what I think after months of using it

#16
post #15

Earlier quoted context omitted.

Shadowing always has been a feature, doubly so in languages which lack linear types. It is a promise to the reader (and compiler) that I will have no need of the old value again. Notice that applying the naming convention you suggest does nothing to prevent the bug in the code you quoted. It might be just as easy to write const initial_foo = Foo.init(); > const foo_feature_A = try initial_foo.addFeatureA(); > const f…

Said promise should also be checked for sanity. E.g. for i in range(N) { for i in range(M) { # Typo; wanted j. # The compiler should complain. } }

The Rust compiler would complain in this case that the initial i variable is unused. Unused variables should be named with an underscore, _.

Re: Zig; what I think after months of using it

#17

It seems like he wants zig to be more like rust. personally, i like that zig is so simple

This is absolutely not what the article is about. A good majority of it is spent on the myth that Zig is safer than Rust, which has nothing to do with wishing Zig was more like Rust.

Re: Zig; what I think after months of using it

#19
post #7

When did shadowing become a feature? I was under the impression it's an anti-pattern. As per the example in the article > const foo = Foo.init(); > const foo2 = try foo.addFeatureA(); > const foo3 = try foo.addFeatureB(); It's a non issue to name vars in a descriptive way referring to the features initial_foo for example and then foo_feature_a. Or name them based on what they don't have and then name it foo. In the e…

Don't see how it could introduce bugs. The point of replacing a variable is precisely to make a value that is no longer needed inaccessible. If anything introducing new variables with new names has the potential to introduce subtle bugs since someone could mistakenly use one of the variables that is no longer valid or no longer needed.

Re: Zig; what I think after months of using it

#20

The debate between static and dynamic typing continues unceasingly. Even when the runtime values are statically typed, it's merely reprised at the type level.

The debate seems to have mostly ended in a victory for static types.

The largest languages other than Python have them (if you include the transition from JS to TS). Python is slowly moving toward having them too.

Post reply on HN