The feature you describe would do two different things, both making the value of a variable immutable, and also prevent reassignment to a variable. Both of those things are individually already possible and combining them would create a whole lot of messy edge cases.
Immutable Variables
Both options are already possible. As you note, you can just rebind a let
variable as const
in Javascript:
let a=[];
const b=a;
// but note you can still change the value
b.push(12);
Python has no feature for immutable variables. You could argue it would benefit from such a feature.
Immutable Values
In Javascript you can create immutable values using Object.freeze(...)
:
let k = Object.freeze({"self": {"king": "henry"}});
k.baz = 15; // errors in strict mode
let m = k;
m.foo = "bar"; // also errors since it points to the same object
k.self.king = "Charles"; // fine, only the top level is protected
k = []; // fine
Outside of strict mode any attempt to modify will just do nothing but give no errors in JS
Python also has various mechanisms to prevent modifications, like tuples, frozensets, frozen dataclasses, named tuples, etc. They work in the same way.
Why combining the two is a bad idea
Convenience
First of all it would just be less convenient than the existing options.
const a = Object.freeze({...});
Is 1 line shorter than
let a = {...};
freeze a;
Recursion
You don't specify if freeze
should act recursively or just prevent modifying the top level value. Both seem bad.
- If you don't recurse, you'd need to individually freeze every property of a large object, adding to the inconvenience above. With
Object.freeze
at least you can do it inline
- If you do recurse, you couldn't freeze anything that had a reference to something that you didn't want frozen. Does your object contain a reference to some HTML element? Well now your entire
window
object is frozen and you can't do anything anymore. Essentially it would effect things way outside the "scope" of the current statement leading to large scale unexpected effects.
Freezing expressions
If you run:
function k() { return [5,3,2] };
freeze k();
What should happen?
There seems to be a very limited type of expressions where your freeze
would actually make sense, leading to a lot of special casing. Other similar operators like delete
work properly for all expressions.
Conditionally freezing variables
You mention this code in your example:
let foo = 0;
let bar = 1;
// Some operations involving foo and bar
const cond = /* A boolean value resulted from the operations */;
freeze cond ? foo : bar;
However, immutability is just a tool to help a programmer avoid mistakes. It is still the programmers responsibility to avoid mutating the variable or the program will crash. So if you want to avoid crashes, you don't mutable even a possibly immutable object. Thus this would effectively just prevent the programmer from mutating both foo
and bar
so you might as well freeze both.
If you later branch and do either something with foo
or with bar
you might as well move the re-declaration inside the condition.
const foo = [];
prevents rebinding likefoo = [1, 2, 3];
but doesn't prevent mutating the array likefoo.push(5);
. In contrast,let bar = Object.freeze([]);
is the opposite in both respects. $\endgroup$Object.freeze
? Or something like Ruby'sObject#freeze
? How does your proposal differ from each of those? $\endgroup$