These are 2 proposals in 1, because I think (I may be wrong) they work better together. However, they can be split into separate proposals.
Mut "expiration"
This is about limiting the number of times a variable can be assigned, either statically (syntactic and lexical) or dynamically (at runtime). Examples:
//var can only be assigned twice (after declaration) at runtime
const 2 x = 0
//loop runs twice until error is thrown
//`x === 2` before the loop halts
while (true) x += 1
//suppose the previous loop hasn't crashed...
//var can only be assigned at most 2 "places" in the code
synconst 2 y = 0
//this never crashes
//the var is only assigned at 1 "place" multiple times
for (let i = 0; i < 256; i++)
y += 1
//despite never running, it still counts as "syntactic assignment"
if (false) {y = 2}
y = 3 //syntax error
These are specially useful when a variable should be immutable but its value must be computed dynamically once or more times.
const 0is identical toconstsynconst 0is an stricter version ofconstconst Infinityis a syntax error (becauseInfinityis not an integer)synconst Infinityis identical toletconst -1andsynconst -1are undefined behavior (it may be defined later)
Reverse declarations
Suppose we have the following:
//"..." means "do something, but don't declare vars"
//...
{
let a = 0
//...
{
let b = 1
//...
{
let c = 2
//...
}
//...
}
//...
}
//...
This "indentation penalty" discourages the good practice of local variables. What if we could do something like?...
//...
let a = 0
//...
let b = 1
//...
let c = 2
//...
undef c
//...
undef b
//...
undef a
//...
This is equivalent to the delete operator (and drop in Rust), except that undef only works on vars declared via let & const. Attempting to undef a variable declared with var or a property of globalThis throws an error (it may be at runtime or "compile"-time)
To discourage abuse of undef, it should have a longer name, like undeclare. Another mechanism to enforce maintainability of code (maybe it's the opposite?, I feel this is wrong), would be to have different keywords associated with the kind of declaration: unconst can only undeclare const, and unlet corresponds to let, mismatching results in an error.
A cool feature of undef is that it can emulate the mut-expiration feature:
let x = 0
//...
x = 1
//...
//re-declare x as a constant
const x = undef x
//undef is an operator that returns the value before deleting it
x = 1 //error
const y = 0
//...
//this is forbidden, because it would destroy the guarantee that `const` is immutable
let y = undef y //error