Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This is my take as well. The older and more travelled I get the more I disdain these kinds of things. Your language syntax should do whatever the "thing" is that your language model is all about. Syntactic sugar should be for the things you do LOTS.

I watch language after language add sugar to maintain the appeal of their product, one niche group or application at a time. It turns into a death by a thousand cuts, or by a thousand sugar cubes. Most languages start out simple and appealing and understandable, an increasingly short amount of time later, they've layered on "helper" after "helper" to the point it takes a bit of expertese to consume the language effectively.

I dream of a world where we'd measure languages by the complexity of their ASTs rather than their popularity on a TIOBE or StackOverflow index.



Arguably this change to the zig language is overall a simplification because the loop index capture is no longer a special case.


Could be. I think you're more the expert here than me? :D

To me, the followin is a bit of syntactic sugar that I think is the kind of transcendental "go big/basic with it" that I hint at.

Some time ago, I worked in a language that had this idea that any composable block of code could be captured as 0-N statements between the characters [ and ]. They thought they were being clever and called it a "block of code". Which I thought was cool, because it looked like a block. Pedants called it a BlockClosure. If you wanted to pass parameters to one of these, they used a colon denoted list. So a two arg block might look like

[:a :b | <code goes here> ]

So yay, pass a closure to a service, and it "captures" the values be invoking said closure with arguments.

And then the authors thought, okay, enough sugar for a few days, let's just use this. I mean really really really use this.

You can use a two arg block like that for a zip function of course, but why limit it to iteration? Use it in the standard library to implement the "for each" function. Which when you looked at was just that "how dare they not have a for syntax" while implementation. But because it wasn't embedded in the syntax, you could copy/paste/modify to come up with a filter iteration. Or a reduce. Or a map. Or all kinds of interesting compositions "selectAndCollectAndReject" with 3 closures.

And why stop there? They decided, "let's just do boolean logic with these block things too". So where as most languages has special syntax for conditionals (and once they start, they're in competition with their peers to keep adding more and more of them (do while, case, if, if with N elses, on and on). But they just wrote it like

<condition> ifTrue: [trueBlock] ifFalse: [falseBlock]

Sure they optimized it, but from a linguistic point of view, it was the same thing as above. No new sugar was needed.

Whereas many languages have added sugar for optionals (usually involving ?s), this language, 20 years ago, was doing it with closures already. Someone noticed they could implement the following family of "functions"

ifNil: [nilBlock]

ifNil: [nilBlock] notNil: [:notNilValue | notNilBlock]

ifNotNil: [:notNilValue | notNilBlock]

Sure, not as terse as ? (which some endeavoured to deal with), but the language semantics didn't have to change each time there was a new thing to do.

I'm sure there's a Lisper out there that can write their analog to the above. Because it too, is was one of these "do much with little" langauges.


You're essentially describing Lisp already.


Working on low level performance sensitive code in games, this is something I see in code LOTS.

As mentioned in the article, data oriented design runs into the pattern of wanting to iterate over parallel arrays of data frequently.


"Sugar" is implemented by converting an AST into itself, so it wouldn't change its "complexity" at all.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: