Not entirely sure about that. At the very least, I haven't seen any situation in which a keyword is not a keyword unless the code is wrapped inside a version check [1]. Nor could code written in older versions of the language predict that it needs to version-protect its variable definitions, lest they become keywords in the future.
But yes on limiting to major versions. If you're releasing a major version, it's under the assumption that code written for previous versions is going to break. That's when the prime opportunity for adding new keywords is.
New syntax, however, has the potential to be added at any time. The best example would be JavaScript, which has no major versions, in the classical sense [2]. When introducing generators, the syntax function* was used, instead of adding a keyword generator. The reason this was okay is because * is not a valid name for a function in JavaScript, so function* is a syntax error. This means no script that works correctly on older browsers could possibly contain function*, so there's no risk of ambiguity.
Which would make coding in the language's latest version really cumbersome âŠī¸
A modern web browser must be able to run websites written in the 90s, as they would run on a browser written in the 90s. âŠī¸
Maybe better than versioning attributes would be to have provisional keywords, with some prefix/suffix that cannot appear in normal names. Then programmers would get a warning for names that are going to become a keyword in the next major version. Before the major release only the provisional keyword is valid, and after the release both the provisional and the actual keyword (and warnings become errors).
Anyway this is off-topic. Thank you for your answers.
Doable, but convoluted. Some languages simply ensure identifiers and keywords are never in the same namespace. Like prefixing keywords with @, or variables with $.
"Just make it a syntax error in older versions" is so much simpler and cleaner.
Actually, I kind of like it. Especially since
break = value
Is a clear syntax error that doesn't require a label.
However, for defensive purposes, I would suggest still requiring an implicit label definition, i.e.
let value = _: do { // Use _ as a throwaway label
if Bool.random() {
break = "Heads" // Returns from the `do` not the `if`, because the `if` has no label
}
break = "Tails"
}
You could say the if here is not an expression. But it could easily be:
let value = {() in // Single-line closure is interpreted as expression
_: if Bool.random() { // Expressions are "infectious": An `if` inside an expression is also an expression
break = "Heads" // Returns from `if`
}
else {
break = "Tails"
}
}()
Unless you disallow an expression without starting with let value = or break =, but the ship has sailed on that one.