6 ms·
> 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) th
by pron 3y ago
> 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.
- the_duke 3y agoI'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.
- pron 3y agoThe 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.
- auggierose 3y agoIt's not really surprising that purely functional programming is expressive. Indeed, it is as expressive as "opaque" programming.
- pron 3y agoThere'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.
- whateveracct 3y agoCan 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 misunderstanding. But the bog standard FP definition is a real and useful concept. Maybe it stole something else's name? But I don't think it's due to being mistaken. Because the FP concept itself is pretty rigorous.
- pron 3y ago> 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 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 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".
- distcs 3y ago> 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. What are some other examples of such languages that rely on second-order languages? You mentioned Lisps. Would Forth be another example? Are there more examples?
- pron 3y agoC++ templates. Also the rich type-level language in languages like Idris (these are qualitatively different, but I'd say they're another example of a second-language-within-a-language that operates at a different level of objects).
- ImprobableTruth 3y agoIf type level functions are a "second language", then so is Zig's comptime.
- pron 3y agoIt's not. comptime reifies types as regular objects (pretty much like maps), so you're not working at the type level; it's no more of a second language than reflection in Java. Of course, you cannot express things like the famous vector concatenation that's expressible with dependent types (https://gist.github.com/cbiffle/82d15e015ab1191b73c3 https://gist.github.com/cbiffle/82d15e015ab1191b73c3) (unless the vector sizes are known at compile time, obviously).
- spenczar5 3y agoI think Ruby is sometimes used in a way that looks second-order. It allows so much metaprogramming that you can really make a full DSL. For example, RSpec: describe "order" do it "is marked as complete" do expect(@order).to be_complete end it "is not yet shipped" do expect(@order).not_to be_shipped end end
- ImprobableTruth 3y agoYou still have to memorize the "design patterns" that replace 'missing' features. Especially annoying for something like interfaces where there's a bunch of variants and people often use implementations with awful error reporting reminiscent of C++ templates. Now, it's definitely neat that you can do reasoning from first principles on it, but I'm not sure how much of a gain that is.
- mannykannot 3y agoOn the other hand, Brainfuck.