
How necessary are var, let, and const? - tbassetto
http://raganwald.com/2015/05/30/de-stijl.html
======
moogly
I found this article's premises and findings rather pointless, and kept on
wanting the author to instead verify the premise "are there actually valid
uses of 'var' now that 'let' exists?" (I haven't found any yet, and I'd like
to know if I'm wrong). But maybe I'm too much of a pragmatist rather than an
academic, so I suppose it wasn't written for me.

~~~
serve_yay
Yes! Thank you. I agree the question is as you pose it -- why use `var`, ever?

~~~
Animats
"let", of course, is a retrofit to Javascript. So was "var". In the early days
of Javascript, before "strict mode", few people declared anything and most
variables had global scope.

It's really hard to get a declaration-free language right. Python was the
biggest success to date.

~~~
chc
Huh? `var` was not retrofitted. I distinctly remember it being there since I
started learning JavaScript, like around '96\. It is true that a lot of people
were slack about using it, but that's just laziness, not that it wasn't there.

------
pm24601
const IS valuable and necessary.

1) It means that every place the const appears it can be replaced with the
const's value. Type checking can be streamlined, less indirection.

2) It communicates the developer's INTENT in an enforced manner. No later code
change can accidentally make the const suddenly non-const.

3) const + deep Object.freeze() makes for a complete const.

Sure a human could hypothetically scan the code to see that the value has not
been reassigned. This falls apart in practice. As soon as the company has a
few dozen developers the code is constantly changing and such manual analysis
would have to be constantly done.

~~~
titzer
1.) is simply wrong. Const variables have a live-range hole where access to
the variable either throws or returns undefined, depending on the language
mode (and the VM!). In either case it _not_ legal to just smash in the
constant.

2.) That's nice but JS semantics do not actually hold up. The intent is for a
constant, the reality is there is a small window where the wrong results can
be observed. Engines don't actually do any more optimizations than for var or
let; in fact, your code may actually be slower due to the live-range hole
checks.

~~~
pm24601
So you are saying that there are race conditions currently? Are any of this
race conditions actually required by the language spec? If not, I suspect that
those race conditions will be eliminated.

~~~
david-given
I believe that what the parent meant was that this:

function f() { console.log(a); const a = 1; console.log(a); }

...actually returns this:

undefined 1

So you get partially compile-time semantics (you can't assign to a) but
partially run-time semantics (a only gets its value when initialised). Simply
propagating the value of a's initialiser to all places where the variable is
used is wrong, as this behaviour's required by the spec.

~~~
AgentME
Actually that code example should throw an exception when the first `a` is
evaluated.

~~~
nullz
It doesn't in v8 -- what do you mean by `should`?

~~~
egeozcan
It's an implementation error. In Firefox, it correctly throws:

> ReferenceError: can't access lexical declaration `a' before initialization

~~~
titzer
No, legacy const is not spec'd by ES5. It behaves differently in FireFox and
V8 because it was added at different times with different semantics in the
live range hole case. In strict mode, it will throw on V8 as well.

------
magice
Hmm, posts like this make me want to make Lisp mandatory for all programmers.
Given that LISPers have argued for "lambda the ultimate kitchen
utensil/sinks/cooks" for the last few decades, it's slightly annoying that
people from other languages repeat the point now. That said, congratulation
for learning value of syntactical sugar. I hope you like it.

That said, can somebody implement hygienic macros in JavaScript. They will
probably help will people having to explain basics knowledge over and over.

~~~
JadeNB
> Given that LISPers have argued for "lambda the ultimate kitchen
> utensil/sinks/cooks" for the last few decades, it's slightly annoying that
> people from other languages repeat the point now.

Why? Are you also annoyed by calculus students who learn ideas today that have
been known for hundreds of years?

> That said, congratulation for learning value of syntactical sugar. I hope
> you like it.

Maybe I am misreading this (it could mean simply what it literally says), but
I read it as unconstructive snark.

~~~
kbenson
I suspect that if mathematicians who were creating alternate number systems
without calculus were continually learning the usefulness of calculus and
telling the world, then yes, those who advised its inclusion for years would
be annoyed, if only because it took so damn long and so much time was wasted.

~~~
JadeNB
Assuming that one is a fan of the sort of abstract computer-scientific
approach to programming embodied by Lisp (and I am!), then it should be a
_good_ thing when people discover it.

Is there a benefit in spreading this discovery to others, even after it's been
known so long? Certainly I think so; it's new to everyone at some point, and,
since I wasn't originally motivated to read McCarthy's original papers, I
wouldn't have discovered the ideas of Lisp without recent expositions of it.
Granting the benefit of this, who can better communicate with the
unenlightened, in terms familiar to them, than a recent convert? (Although, as
braythwayt points out
([https://news.ycombinator.com/item?id=9641279](https://news.ycombinator.com/item?id=9641279)),
he is scarcely a newcomer to the party.)

------
ylg
Interesting and well written; if it were me, I might only change the ending a
bit:

"Whereas, const […]. _It is not nearly as useful as immutable data, because
the problem it solves is easy, not hard._ "

To something like:

"const may be more useful than adding something like immutable data to an
imperative language with mutability deep in its DNA might be because it helps
with one of the hardest problems; long-term, _correct_ re-reading by humans
doing maintenance or extension."

But, the OP covers that well earlier in, so I'm not sure a third take on it
would add much. Thanks for doing the exploration!

------
serve_yay
Can you eliminate `var` by introducing an unnecessary function, declaring the
`var`s as parameters, and then invoking? Yes you can.

Why you would ever do that, however...

~~~
tperson
This was my thoughts exactly. I stopped reading after that section. I don't
understand what the author is trying to do.

------
bmeck
const can be used to denote that a reference to the variable is being passed
around and should not change for the lifetime of a scope.

    
    
        function f() {
          const queue = [];
          consumer(queue);
          return queue;
        }
    

It could be important to note that removing const has benign effect, but that
it is there to ensure a programmer does not change the value of queue between
`consumer(queue)` and `return queue`. Easily reasoned about, but extra
safeguards from introducing bugs is always nice.

~~~
EugeneOZ
Ironically enough, but your example shows where const is shouldn't be used as
guarantee of immutability: [https://t.co/JIQozGe7Md](https://t.co/JIQozGe7Md)

~~~
agumonkey
Isn't that a typical "corner case" in the understanding of dynamic languages
bindings ? I think I've seen the same question pop about python. The array
binding is constant, its content isn't.

~~~
EugeneOZ
if value of constant can be changed, it's not constant. In my understanding.
And by Wikipedia:
[http://en.wikipedia.org/wiki/Constant_(computer_programming)](http://en.wikipedia.org/wiki/Constant_\(computer_programming\))

~~~
agumonkey
That's typical computer lingo / semantic issue. the `const` mean
shallow/pointer constant, not deep/structurally constant.

------
rbalicki
If we use the approach of converting var's to named parameters, we also have
to give up on passing variable numbers of arguments to functions. That is,
unless we do something silly like:

    
    
        function silly(x, y, z, args) {
          args = Array.prototype.slice.call(arguments);
          args.shift();
          args.shift();
          args.shift();
          args.shift();
          x = y = z = undefined;
    
          // regular function goes here
        }

~~~
shawndumas
The replacement of var or let was a thought experiment to show the actual
value--in code--of using them.

------
pc2g4d
Does anyone else out there think Javascript `const` should really be called
`final`? It more closely mimics Java's `final` keyword by preventing
reassignment ("rebinding") of the variable, whereas `const` makes me think of
full immutability as in C++.

------
bshimmin
OK, I'll bite: what does De Stijl
([http://en.wikipedia.org/wiki/De_Stijl](http://en.wikipedia.org/wiki/De_Stijl))
have to do with any of this?

~~~
gjm11
It was a movement that attempted to achieve clarity and elegance by omitting
the unnecessary -- and the article discusses whether omitting formally-
unnecessary features like _var_ or _const_ makes for more clarity and
elegance, or less.

(Having said which, I notice that there's a reply from the person who actually
wrote the article, and it doesn't say that. But that's why he _should_ have
made the reference :-).)

~~~
braythwayt
I might have said that, but then I would be omitting the fact that not
everyone finds my reproduction of the red-=blue chair comfortable.

Scheme vs. Common Lisp, and all that.

------
shawndumas
To be fair; getting the benefit of const _would_ require code too though:

    
    
      function constUseful () {
        var guarded = 1;
    
        (function loop (orgGuarded) {
          setTimeout(function () {
            if (guarded !== orgGuarded) {
              throw 'guarded reassigned!';
            }
            loop(orgGuarded);
          }, 0);
        })(guarded);
    
        guarded = 2;
      }
    
      constUseful();
    

That's an approximation of const's value as delineated in code.

------
protonfish
A better question is how useful is _let_ at all? Having two different variable
scoping rules with no way to know which one a variable is using without
backtracing sounds like a maintenance nightmare. I understand what is it good
for, but it seems like we are replacing a small problem with a bigger problem.

An even better question is why not get rid of _var_ and make every variable
local to its parent function? To alter globals, use the window object
explicitly.

~~~
hrjet
> To alter globals, use the window object explicitly.

JS is used in non-DOM contexts as well. Though, of course, if that big a
change is being made, a generic substitute for `window` could also be
specified.

~~~
reubenmorais
> a generic substitute for `window` could also be specified

Isn't that just |this| at the top level?

~~~
singlow
Not necessarily the _top_ level if you are referring to scope. `this` will be
the default global unless another context is defined, whether you are at the
top level or inside a function.

In node, there is a name for the default global: "global", which is also the
default context. So node gives it a "generic substitute" as the OP suggested.
Most people use "this" to make assignments to it, rather than the "global"
name, since it is usually accessed from the default context.

------
rashkov
Could anyone please explain to me why the author chose those functions for his
examples? I got as far as callFirst() and repeat() and found it hard enough to
wrap my mind around the functional / meta programming within. Are those
actually good examples? It seems like there are simpler ways to illustrate the
point.

~~~
fenomas
If you check out Javascript Allonge (linked on the page, web version is free)
you'll find out. The author has written a lot about functional programming,
combinators and so on in JS.

I think his point was simply that examining how to emulate let/var with
closures, it shows you explicitly what is different/similar about them. He's
not suggesting anyone use those transforms.

------
aikah
let is obviously needed(devs like lexical scoping) but I found the whole var +
let in the same language thing a bit confusing. The temptation to introduce
yet another strict mode(to forbid var,and a few other constructs) is strong on
this one.

~~~
braythwayt
var vs. let in the same language is a consequence of designing the language by
committee, requiring 100% backwards-compatibility, and forbidding the addition
of new modes (which is a back-door way to introduce breaking changes, while
requiring browser vendors to essentially support multiple versions).

~~~
sebleblanc
That behaviour is not exclusive to standards committees. The government and
private companies do it all the time.

~~~
CrossEye
"governments and private companies" certainly do not preclude committees.
Quite to the contrary, in fact.

------
riffraff
> You can see every single rebinding of a variable within the lexical scope of
> the function,

I do not think that is true, a called function can side effect the caller
environment via `arguments` if that is passed around.

~~~
braythwayt
My understanding is that arguments caller has been removed, and
Function.prototype.caller is non-standard:

    
    
      > The obsolete `arguments.caller` property used to provide the
      > function that invoked the currently executing function. This
      > property has been removed and no longer works.
    

[https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Functions/arguments/caller)

Can you provide an example of modifying a declared variable in a calling
environment? I'm very interested!

~~~
riffraff
I meant this:

    
    
        function sidEffecting(ary) {
          ary[0] = ary[2];
        }
        function bar(a,b,c) {
          c = 10
          sidEffecting(arguments);
          return a + b + c;
        }
        bar(1,1,1) // I expect 12, but is 21
    

I now realize this could actually be not allowed anymore in recent ES, I am
not sure, but copy & paste in chrome console still prints 21.

------
btbuildem
That disclaimer is a bit of a cop-out, given the subject matter..

