←back to thread

Zig is hard but worth it

(ratfactor.com)
401 points signa11 | 3 comments | | HN request time: 0s | source
Show context
pron ◴[] No.36150237[source]
> there’s not a direct correlation between the slimness of a language’s syntax and ease of learning

That's absolutely true, but (the standard library aside) the "syntax" -- or, rather the syntax and core semantics -- of a programming language are arbitrary axiomatic rules, while everything else is derivable from those axioms. So while it is true that a small language can lead to a not-necessarily-easy-to-learn overall programming experience, it is the only arbitrary part, and so the only part you need to memorise (or consult the documentation for when dealing with some subtlety you may have forgotten). So a smaller language reduces the need for "language lawyering" after you learn it.

Some languages (e.g. lisps) are deceptively small by relying on macros that form a "second-order" language that interacts with the "first-order" language, but Zig doesn't have that. It has only one language level, which is small and easy to memorise.

But yes, Zig is a bigger language than C, but a far smaller language than C++. What's amazing, though, is that C++ is strictly more expressive than C (i.e. there are programs that could grow exponentially faster in C than in C++, at least without the help of C macros), but Zig is as expressive as C++ (i.e. program sizes may differ by no more than a small constant factor) while being much closer to C in size, and it achieves that without the use of macros.

replies(4): >>36150398 #>>36150954 #>>36151058 #>>36153690 #
the_duke ◴[] No.36150398[source]
I'm not a Zig expert, but I have a different take here.

Zig has comptime, which is essentially a compile time macro written in the main language and with type reflection capabilities.

They can introduce complex behaviour and fail in very cryptic and unexpected ways, which results in an experience very similar to macros or C++ template literals.

replies(1): >>36150717 #
pron ◴[] No.36150717[source]
The objects that are manipulatable by comptime are ordinary program objects and types -- not ASTs. That means that while it's true you can get compile-time errors in similar situations to macros, the errors themselves are like ordinary runtime errors in an untyped language -- while occurring at compile-time, they look like runtime error in Python or JS -- rather than errors due to some "second-order" manipulation of symbols like templates or macros, and so are easier to diagnose (you get a regular stack trace for one).

There is also another interesting difference, albeit a theoretical one. Zig's comptime is what's known in formal languages to be referentially transparent (it basically means that you cannot distinguish between two otherwise identical objects that differ only in their reference name) while macros are not. Because referential transparency is strictly less expressive than "opacity" (but it's also simpler!), it's surprising that so many practical use cases for macros can be addressed with the less powerful (but simpler and much easier to debug) comptime. That's quite a discovery in language design. While other languages also have comptime-like constructs, they also have other complex features that have made it hard to see just how powerful something like comptime alone can be.

replies(3): >>36151303 #>>36151943 #>>36156263 #
auggierose ◴[] No.36151303[source]
It's not really surprising that purely functional programming is expressive. Indeed, it is as expressive as "opaque" programming.
replies(1): >>36151398 #
pron ◴[] No.36151398[source]
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 programming, a referentially opaque expression can refer to the name of the variable holding some value. In programming, languages like Zig and Java are more referentially transparent than languages like C and Haskell because the latter have macros.
replies(2): >>36151778 #>>36151826 #
auggierose ◴[] No.36151826[source]
Referentially transparent means that you can replace an expression with its value without changing the meaning of the program. If everything you can do must be referentially transparent, then that's purely functional programming, because applying functions without side-effects is pretty much the only thing you can do then. Of course, there are some other techniques like rewriting, which strictly speaking are different from purely functional programming, but I consider these two things to be pretty much the same thing.
replies(1): >>36152488 #
pron ◴[] No.36152488[source]
> Referentially transparent means that you can replace an expression with its value without changing the meaning of the program.

Not quite. A referentially transparent expression (E) is one where you can replace any of its subexpressions (A) with another (B) that has the same meaning (not value!!!!) as (A) without changing the meaning (not value!!!) of E. However, in purely functional languages, the meaning of any expression is a value, but that's the important thing about them, not the fact that they're referentially transparent as imperative languages equally are. We often use the word "semantics" or "denotation" instead of "meaning" in the above, and we say that a pure functional one is one that has "value semantics", i.e. one where the meaning of an expression is a value.

Most programming languages are referentially transparent when not using macros (that was the whole point of talking about referential transparency in programming in the first place), and that's important because it demonstrates both the expressive power and the complexity of macros.

replies(2): >>36153708 #>>36154329 #
norir ◴[] No.36153708[source]
Do you have sources for your definition? The original definition that I'm finding from Quine seems to broadly support the interpretation that an expression is referentially transparent if it can be replaced by its value without altering program semantics, as others have stated. Regardless, it isn't clear to me how macros are any more or less referentially transparent than function calls in an impure language.
replies(2): >>36153732 #>>36154447 #
1. whateveracct ◴[] No.36153732[source]
I'm very sure the commenter is being a little pedantic

But even pedantry can't argue that Java is a fundamentally more referentially transparent language than Haskell lol. That threw me for a loop.

replies(1): >>36154477 #
2. pron ◴[] No.36154477[source]
Right, the incorrect and quite pointless common use of "referential transparency" in FP fan circles tends to throw people off when they first see and understand the actual meaning of the term.
replies(1): >>36156125 #
3. whateveracct ◴[] No.36156125[source]
Well it's not pointless. The term as used in FP has a pretty well-defined meaning [1] and it is a quality only some programs have. And a program having that quality enhances (fast-and-loose) equational reasoning.

[1] I can point at most Java code and prove how it fails the definition. It's not especially hand-wavey.