No Semicolons Needed (terts.dev)

by karakoram 89 comments 64 points
Read article View on HN

89 comments

[−] Animats 56d ago
Classic mistakes in language design that have to be fixed later.

- "We don't need any attributes", like "const" or "mut". This eventually gets retrofitted, as it was to C, but by then there is too much code without attributes in use. Defaulting to the less restrictive option gives trouble for decades.

- "We don't need a Boolean type". Just use integers. This tends to give trouble if the language has either implicit conversion or type inference. Also, people write "|" instead of "||", and it almost works. C and Python both retrofitted "bool". When the retrofit comes, you find that programs have "True", "true", and "TRUE", all user-defined.

Then there's the whole area around Null, Nil, nil, and Option. Does NULL == NULL? It doesn't in SQL.

[−] tadfisher 55d ago
That's what's nice about coarse-grained feature options like Rust's editions or Haskell's "languages", you can opt in to better default behavior and retain compatibility with libraries coded to older standards.

The "null vs null" problem is commonly described as a problem with the concept of "null" or optional values; I think of it as a problem with how the language represents "references", whether via pointers or some opaque higher-level concept. Hoare's billion-dollar mistake was disallowing references which are guaranteed to be non-null; i.e. ones that refer to a value which exists.

[−] dfawcus 55d ago
Attribute (qualifier), or storage class?

https://www.airs.com/blog/archives/428

The use of 'const' in C is very much a mixed blessing; I certainly have experience of the 'const poisoning' issue. Possibly it would have been better as a storage class.

For bool, yes it was a useful addition. Especially for the cases where old code would have something like:

    #define FLAG_A 1u
    #define FLAG_B 2u
    int has_flag_B (something *some) { return some->field & FLAG_B; }
and that was then combined with logic expecting 'true' to be 1; which could sneak in over time.
[−] Ferret7446 55d ago

> Does NULL == NULL? It doesn't in SQL.

That's because SQL null is semantically different. Most nulls are a concrete value (null pointer). SQL null is the relational null ("not known"). It's closer to NaN (but still different)

[−] bmandale 56d ago

> I would love to see a language try to implement a rule where only an indented line is considered part of the previous expression.

After python, it seems like every language decided that making parsing depend on indents was a bad idea. A shame, because humans pretty much only go by indents. An example I've frequently run into is where I forget a closing curly brace. The error is reported at the end of the file, and gives me no advice on where to go looking for the typo. The location should be obvious, as it's at exactly the point where the indentation stops matching the braces. But the parser doesn't look at indents at all, so it can't tell me that.

[−] Joker_vD 55d ago
Perhaps having unary minus (and especially unary plus) is just a bad idea in general; just mandate "0 - expr". To make negative constants work properly, you still have to either special case literals "256", "65536", etc. and ideally check whether they got negated or not, or introduce a special syntax just for them, like "~1" of ML for negative one, or "-1" (which you are not allowed to break with whitespace) of some other language I've forgotten the name of.

While we're at it, probably the unary bitwise complement could go as well? Obviously, "^(0-1)" would suck to write but since 99% of the time bitwise "not" used in expressions/statements like "expr &~ mask..." or "var &= ~mask", I feel like simply having binary "and-not" operator that looks like "&~" or "&^" (Golang) is just better.

Also, a small prize (a "thank you!" from a stranger on the Internet i.e. me) to someone who can propose a good syntax for compound assignment with reversed subtraction:

    x ^= 0-1    # in-place bitwise complement
    x ^= true   # in-place logical negation
    x ?= 0      # in-place integer negation???
[−] librasteve 56d ago
This article makes a strong case for every language to use ‘;’ as a statement separator.
[−] marcosdumay 56d ago
Looks at 11 languages, ignores Haskell or anything really different...
[−] sheept 56d ago
Because formatters are increasingly popular, I think it'd be interesting to see a language that refuses to compile if the code is improperly formatted, and ships with a more tolerant formatter whose behavior can change from version to version. This way, the language can worry less about backwards compatibility or syntax edge cases, at the cost of taking away flexibility from its users.
[−] sheept 56d ago

> I would love to see a language try to implement a rule where only an indented line is considered part of the previous expression.

Elm does this (so maybe Haskell too). For example

    x = "hello "
     ++ "world"

    y = "hello "
    ++ "world" -- problem
[−] kayson 56d ago
Are we really saving that much by not having semicolons? IDEs could probably autocomplete this with high success, and it removes ambiguity from weird edge cases. On the other hand, I've not once had to think about where go is putting semicolons...
[−] Mawr 55d ago

> The first thing that I dislike about this is that it encourages thinking of semicolons being inserted instead of statements being terminated

It might, but that's irrelevant since you never think about semicolons in Go at all.

> I like these formatting choices, but I'd prefer if the "wrong style" was still syntactically valid and a formatter would be able to fix it.

Your preference likely comes from some idealistic idea of "cleaniness" or similar, which isn't very convincing. Forcing everyone to use the same style is a huge win, to the point that it's a mistake to do anything else, as seen in the description of what Odin does. Completely wrong priorities there and refusal to learn from the past.

"Code formatting" isn't some inherent property of code that we must preserve at all costs, just a consequence of some unfortunate syntactical choices. There's no inherent reason why a language needs to allow you freedom to choose how to "format" your code. And there are in fact a lot of reasons why it shouldn't.

[−] IshKebab 56d ago

> how does Gleam determine that the expression continues on the second line?

The fact that it isn't obvious means the syntax is bad. Stuff this basic shouldn't be ambiguous.

> Go's lexer inserts a semicolon after the following tokens if they appear just before a newline ... [non-trivial list] ... Simple enough!

Again I beg to differ. Fundamentally it's just really difficult to make a rule that is actually simple, and lets you write code that you'd expect to work.

I think the author's indentation idea is fairly reasonable, though I think indentation sensitivity is pretty error-prone.

[−] i_don_t_know 55d ago
The Haskell language report precisely defines how layout determines structure: https://www.haskell.org/onlinereport/haskell2010/haskellch10...

Any language that uses layout to determine structure should have a similarly precise definition.

[−] teo_zero 55d ago
It's very subjective, and I don't want to say that semicolons are good or bad, indentation is good or bad, etc.

But I think a language should decide whether white space is significant or not. If it's not, don't add exceptions!

Operators changing meaning when surrounded by spaces in otherwise context-free languages are an abomination!

[−] lightingthedark 55d ago
It's interesting seeing all of the different ways language designers have approached this problem. I have to say that my takeaway is that this seems like a pretty strong argument for explicit end of statements. There is enough complexity inherent in the code, adding more in order to avoid typing a semicolon doesn't seem like a worthwhile tradeoff.

I'm definitely biased by my preferences though, which are that I can always autoformat the code. This leads to a preference for explicit symbols elsewhere, for example I prefer curly brace languages to indentation based languages, for the same reason of being able to fully delegate formatting to the computer. I want to focus on the meaning of the code, not on line wrapping or indentation (but poorly formatted code does hinder understanding the meaning). Because code is still read more than it is written it just doesn't seem correct to introduce ambiguity like this.

Would love to hear from someone who does think this is worthwhile, why do you hate semicolons?

[−] gcanyon 56d ago
Can anyone give a good reason why supporting syntax like:

    y = 2 * x
      - 3
is worth it?
[−] stack_framer 55d ago
I never actually type semicolons in my JavaScript / TypeScript. In work projects, my IDE adds them for me thanks to the linter. In personal projects, I just leave them out (I don't use a linter, so my IDE does not add them), and I've never had a problem. Not even once.

Semicolon FUD is for the birds.

[−] gethly 56d ago
[flagged]