Live data from Hacker News

Zig is hard but worth it

ratfactor.com

131–140 of 307 posts

Re: Zig is hard but worth it

#131
post #89

In new last version 0.10.1 it seems that for is not working with two arguments? const std = @import("std"); const expect = std.testing.expect; test "for basics" { const items = [_]i32 {4,5,3,4,0}; var sum: i32 = 0; for(items, 0.. ) |value,_| { sum += value; } try expect(sum == 16); } ubuntu 22.04, snap zig version 0.10.1 , zig test 1.zig produces: 1.zig:7:12: error: expected ')', found ',' for(items, 0.. ) |value,_|…

For loop syntax was changed since 0.10.1.

Zig 0.10.1:

    for(items) |value| {}
    for(items) |value, index| {}
Zig 0.11-dev:

    for(items) |value| {}
    for(items, 0..) |value, index| {}
    for(as, bs, cs, ds, 0..) |a, b, c, d, index| {}

Re: Zig is hard but worth it

#132

My main issue with Zig is that I’m scared to invest time in writing something nontrivial to see the community/adoption flounder then regret not using Rust or C++ later The language itself is fun. The explicit-ness of choosing how allocation is done feels novel, and comptime is a clean solution for problems that are ugly in most languages. Aside from lack of community I’d say the biggest nuisance is error handling in…

I suppose you could write a few line wrapper that panics :) But yeah, most of the time I don't even want to think which allocator to use let alone handle it's errors.

I think for the problem space zig is trying to fit in, it's pretty essential to have custom allocator support thoroughly baked in.

It's the sort of thing that lets a data structure be used on both a gpu and cpu, allocation out of shared memory, or ensure that no dynamic allocations are happening at all.

Most programs don't have those concerns - so zig may not be the best choice for them. For the programs that do have those concerns, forethought about allocators is pretty important. Right tool for the job, and all that.

Re: Zig is hard but worth it

#133

Earlier quoted context omitted.

Zig has a builtin @Vector type that might come in handy for most cases where in C++ a math library with operator overloading would be used: https://www.godbolt.org/z/7zbxnncv6 ...maybe one day there will also be a @Matrix builtin.

Probably not. @Vector is not a mathematical vector, it's SIMD. it makes sense because there are times when those live in registers and a poly fill for stack memory isn't burdensome. @Matrix makes less sense because when it gets big, where are you getting memory from?

For 'game-ey' math code, a matrix is at most 4x4 floats (64 bytes), that's fine for a value type that might live on the stack.

vec2..4 and matching matrix types up to 4x4 is basically also what's provided in GPU shading languages as primitive types, and personally I would prefer such a set of "SIMD-y" primitive types for Zig (maybe a bit more luxurious than @Vector, e.g. with things like component swizzling syntax - basically what this Clang extension offers: https://clang.llvm.org/docs/LanguageExtensions.html#vectors-...).

Re: Zig is hard but worth it

#134
post #7

I get what Zig is going for in making all operations as explicit as possible, but I fear that it's going to turn away fields like graphics and game development where it would be a good fit except for the lack of operator overloading forcing you to go back to C-style math function spaghetti. It's all fun and games until what should be a straightforward math expression turns into 8 nested function calls.

I am not much of a Zig-head, but the best compromise I can think of is having a few operators which purely and solely exist for this purpose. In other words, there is no operator overloading, but you can define, say, "#+" for any two structs, or something like that. So if you want to encode matrix multiplication, then you'll always have to write `mat1 #* mat2`. This feels like a hack, and isn't all that elegant, but…

Maybe an operator-overloading region?

    #{
       m3 = m1 * m2 + m3;
       m3 += m4;
    }
Basically, pure syntactic sugar to help the author express intent without having to add a bunch of line-chatter.

Speaking of operator-overloading, I really wish C++ (anyone!) had a `.` prefix for operator-overloading which basically says "this is more arguments for the highest-precedence operator in the current expression:

    a := b * c .+ d;
Which translates to:

    a := fma(b, c, d)

Re: Zig is hard but worth it

#135
post #81

Earlier quoted context omitted.

In a vacuum, one might prefer Zig. But given that everyone already knows C and the ecosystem is so highly developed, it takes a gamechanging feature like Rust's memory safety to make an alternative language attractive (beyond a "this is cool" project--which I totally support).

I haven't tried Zig, but "all the things you like about C plus better versions of most/all of the awkward bits" seems like a reasonable value proposition. Especially since the compiler can apparently let you use C painlessly alongside your Zig -- enabling incremental rewriting.

Can you use Zig painlessly alongside C? Does `zig cc` or an equivalent provide for writing Zig libraries that then can be called by a main C function?

Re: Zig is hard but worth it

#136

Earlier quoted context omitted.

Zig has a builtin @Vector type that might come in handy for most cases where in C++ a math library with operator overloading would be used: https://www.godbolt.org/z/7zbxnncv6 ...maybe one day there will also be a @Matrix builtin.

That still breaks if you layer any abstractions on top, for example if you wanted to build an AoSoA packet of Vec3s you'd have to define an addition of those in terms of a function. https://www.godbolt.org/z/v8Ta8hEbv Zig is exactly the kind of language where you'd want to build a performance-oriented primitive like that, but AFAICT the language doesn't let you do it ergonomically.

That's true, but OTH that's already getting into territory where operator overloading might start to become detrimental because it hides important implementation details which might not be expected from a simple '+'.

Re: Zig is hard but worth it

#137
post #66

Earlier quoted context omitted.

There's nothing pure functional here (perhaps the term "referential transparency", which some FP fans have come to misunderstand and perpetuate its misunderstanding is what may have given you that impression). Referential transparency is very much less expressive than referential opacity, as there are certain statements that simply cannot be expressed if your language is referentially transparent. For example, in pro…

Can you give me an example of a Haskell expression which isn't reverentially transparent (without unsafePerformIO)? > An expression is called referentially transparent if it can be replaced with its corresponding value (and vice-versa) without changing the program's behavior. ^ that is the definition of referential transparency I am aware of. You seem to be implying that FPers have bastardized the term through their…

> Can you give me an example of a Haskell expression which isn't reverentially transparent (without unsafePerformIO)?

Yes: https://github.com/ncaq/debug-trace-var The trick, however, is not unsafePerformIO (destructive mutability has nothing to do with referential transparency in general, although it breaks it in Haskell specifically) but with TemplateHaskell, as quoting has everything to do with referential transparency.

> But the bog standard FP definition is a real and useful concept.

Actually, it's rather tautological. It defines FP circularly (see my comment here: https://news.ycombinator.com/item?id=36152488). It says nothing more than the far more useful explanation: "the meaning of every expression is a value".

Re: Zig is hard but worth it

#138
post #28

Earlier quoted context omitted.

Idea: allow some weird Unicode operators like Julia does. Then it’ll be clear the weird operator is doing something weird and new. And this already works in other languages. There are lots of Unicode

Writing greek symbols is sufficiently annoying that I always kind of resent code that does this. It’s not just about the first time you are writing code, but also when you are reviewing it, or trying to share a snippet with a coworker, or lots more scenarios. Maybe it’s just me, but writing ‘z = x ∇ d’ is really tedious.

∇ is near-worst-case since it's not even Greek. I think domain-specific keyboard layouts are as much of a good idea as language-specific layouts, but they're a nuisance to install on *nix (trivial on OS X). Using .XCompose is the most practical *nix approach, in the absence of program-specific methods like Julia's tab-completable backslash names.

Re: Zig is hard but worth it

#139
post #38
post #7

I get what Zig is going for in making all operations as explicit as possible, but I fear that it's going to turn away fields like graphics and game development where it would be a good fit except for the lack of operator overloading forcing you to go back to C-style math function spaghetti. It's all fun and games until what should be a straightforward math expression turns into 8 nested function calls.

As someone who works on another language that is relatively reluctant to add language features (Java) we regularly face such dilemmas. A user shows up with a problem that could be helped by the language. The problem is real and a language feature would work, but there are many such problems, and adding features to solve all of them will make the language much bigger, overall causing greater harm (even those who don't…

In robotics, numerical linear algebra expressions comprise a large part of the code base. If not by line count, then definitely by the amount of time spent writing, reading, and debugging such code. This makes Zig unusable for these applications, at least not without additional tooling. You can get a feel for how unergonomic this is by avoiding the use of all arithmetic operators in your code and instead forcing yourself to use user defined plus(a,b), minus(a,b), assign(a,b), etc, or programming directly with the C blas api.

Re: Zig is hard but worth it

#140
post #137

Earlier quoted context omitted.

Can you give me an example of a Haskell expression which isn't reverentially transparent (without unsafePerformIO)? > An expression is called referentially transparent if it can be replaced with its corresponding value (and vice-versa) without changing the program's behavior. ^ that is the definition of referential transparency I am aware of. You seem to be implying that FPers have bastardized the term through their…

> Can you give me an example of a Haskell expression which isn't reverentially transparent (without unsafePerformIO)? Yes: https://github.com/ncaq/debug-trace-var The trick, however, is not unsafePerformIO (destructive mutability has nothing to do with referential transparency in general, although it breaks it in Haskell specifically) but with TemplateHaskell, as quoting has everything to do with referential transpar…

hm okay so basically anything that doesn't use TH or unsafePerformIO is gonna be referentially transparent. And TH is even deferentially transparent at TH-time. It only "breaks it" when evaluating the whole program. But each "stage" maintains the property.

I'm assuming any pure language with macros is also r.t. at each stage and only pedantically breaks r.t. when combined. But I don't think that especially hurts the ability to do fast and loose reasoning so long as the core language is pure.

It definitely doesn't seem correct to say Java is more referentially transparent than Haskell here. You don't have to go into such niches in Java to lose that property.

Post reply on HN