Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It's a great explanation, but I've never heard the term 'binding' used to describe variables. It's usually reserved to function binding or bridge APIs like the DOM.

The tricky thing is that "boxes" are the right abstraction for primitive values. After that you need to explain how references work, and that's pretty much the same 'tentacle' concept. This method spares the reader one step, but might cause confusion once they face problems that require that understanding.




"Binding" is used thousands of times in the language standard, including for variables: https://tc39.es/ecma262/#sec-variable-statement -- that's my point, that this book is precise while being approachable to beginners.

And I dispute the claim that "boxes" are the right abstraction for anything in JS. (Boxes may work for primitive values, but nothing further.) Directly seeing names as bindings ("tentacles") not only skips the incorrect "boxes" step, but also causes no confusion or problems whatsoever at any point. (If you have an example, I'd be curious to see it.) (There are some differences in the language between primitive values and Object, but none of them are particularly helped treating variables as boxes AFAICT.)


I meant in the context of writing code - you’ll never hear anyone refer to their “bindings”.

It breaks down with the simple `let a = 22; let b = a` example where the tentacle/binding metaphor can lead to wrong intuition of why a change to the value of a is not reflected in b.


In what way does it break down? Maybe if one is thinking of boxes, going by "a change to the value of a"? The book says:

> When a binding points at a value, that does not mean it is tied to that value forever. The = operator can be used at any time on existing bindings to disconnect them from their current value and have them point to a new one

In this case:

    let a = 22;
The binding a points to the value 22.

    let b = a;
The binding b points to the same value that a points to, namely 22.

    a = 23;
The binding a now points to a different value 23. The binding b is not affected.

I've linked it a few times in this thread, but see the equivalent article for Python, which explains it clearly: https://nedbatchelder.com/text/names1.html

(It cannot break down because it's how the language works.)


Have you given any kind of training or lessons in programming (honest question)? Everything can break down!

This is exactly what I’m talking about:

> The binding b points to the same value that a points to

It may look obvious to you, but someone will interpret “the same value” as literally the same. So they might expect a change in a to reflect on b. Whereas if you tell them the “a box contains 22” and “the b box also contains 22” you prevent that misunderstanding. They might not have any concept of references/pointers yet and are just trying to make sense out of everything. These are the kind of silly mistakes people make when learning programming, or a new language.

It’s not about being right or wrong but providing a safe path to understanding that can be built upon. I did not mean the binding/tentacle abstraction is wrong, just that there might be a simpler one to introduce the concept. The book is still great regardless.


> It may look obvious to you, but someone will interpret “the same value” as literally the same.

But it is literally the same? Numbers are immutable, so there is a performance optimization where you can avoid using pointers internally, but the fact that they are immutable also means there is no way to distinguish between them being the same value and them being "different instances".

If you do `let a = []; let b = a; a = [1]` would your students expect that b equals [1] or would they understand that a and b now contain different arrays? If the latter, then why would think that after `let a = 22; let b = a; a = 50;` b also equals 50?


> Have you given any kind of training or lessons in programming (honest question)? Everything can break down!

I have actually, so I understand what you mean, that all sorts of confusions are possible no matter what. I agree with you on that part; I just disagree that the “boxes” metaphor is something that is necessary or “needed later” (what I understood from the wording “This method spares the reader one step, but might cause confusion once they face problems that require that understanding” or “breaks down”).

Yes, the student needs to understand that “let b = a” assigns to b the value of a, and does not make b a permanent alias for a. To some students that misconception may never arise, but to others it might and that is something to watch out for. (This is the part explained here for instance: https://nedbatchelder.com/text/names1.html#:~:text=I%E2%80%9... — sorry if you cannot see the highlighted part e.g. if you're using Firefox (https://caniuse.com/url-scroll-to-text-fragment), look before and after "Reassigning one of them".) But if you explain this as “the a box contains 22” and “the b box also contains 22”, this is an understanding that only applies to primitive values and therefore will break down pretty soon and cause confusion (given how widely non-primitive values are used in JS/Python/etc), while if you say that “let b = a” makes the “b tentacle” point to the value that the “a tentacle” points to, this is a uniform understanding that bypasses the incomplete “boxes” understanding. With the understanding that names are one kind of thing and values are another, and names can only point to values (not to other names), there is no problem with “the same value” being interpreted as literally the same: it is literally the same value (a Platonic ideal “22” that lives out there and that both a and b point to), and a re-assignment like a = 23 does not change the value (the notion of changing a value would not even arise without the boxes metaphor, as value 22 and value 23 are simply different things on the values side).

But I guess ultimately this is an empirical matter: we can try the different paths on different sets of students and over time see which one takes better. My intuition is that the “tentacles” metaphor is just as easy to understand as “boxes” without the latter's problems (there are risks common to both, e.g. "let b = a" neither makes the b tentacle point to a itself, nor does it put the a box inside the b box), but until we actually try it out (I have not tried to compare), I guess we just have different intuitions for now. :-)


You're struggling due to a conflation of two concepts.

Binding refers to associating a name with a value. Assignment is a case of binding, but not the only one; two other examples are positional arguments in a function signature, and ESM imports. A binding can be mutable (let assignment, function arguments) or immutable (const assignment, ESM import).

Value mutability is orthogonal. You can mutably bind a primitive value as "let a = 22" and then mutate the binding via reassignment, but you can't mutate the value itself; you can immutably bind a reference value as "const b = {}" and mutate the referenced object via property access, but you can't mutate the binding.

I refer to bindings all the time, where it's useful to be clear in meaning. I also make sure to introduce the concept to mentees who aren't already familiar with it, and by all reports thus far it's proven as valuable an abstraction for them as it did for me when I first learned of it.


That’s funny. This is about didactics for newcomers to the language, I shared an example of what might trip them up. Thanks for taking the time though.


"binding" is a PLT term, denoting the association between a name and a value.

It's a higher level concept than the variable - a mutable binding is what people usually refer to as a variable, and an immutable binding is the correct term for what people refer to an "immutable variable" (an oxymoron, if you think about it).


Immutable variable isn't a oxymoron. It can still vary between instantiations. If you have (a)=>{const b = a}, b can have different values even though it can't be reassigned.


In the case of the code that you have cited, these are all different elaborations of the binding at the invocation of the lambda, due to the interplay between activation records and scope rules.

It's not really an "immutable variable" - it's a local binding getting bound to different values on each scope entry.

EDIT: By the way, the `b` binding in your code can be modified. Did you mean `const b = a;` ?


> it's a local binding getting bound to different values on each scope entry.

It is, I just wanted to point out that the term "immutable variable" is sensible. I think a good way to put it is that b is a variable, and when the statement runs a value is bound to b. So the value bound to b varies yet b can be immutable, in contrast to a constant which is a binding to always the same value.

> Did you mean `const b = a;` ?

Fixed, thanks :)


1) the most common binding used in well written modern JavaScript is a const binding. It is by definition not a variable.

2) the ‘binding/tentacle’ metaphor works just fine for primitives and the ‘boxes’ model adds more complexity.


"binding" is pretty standard terminology in some oldtimey languages; lisp, ML, etc.


Bash documentation says that "set -u" traps variables that are "unset".

The actual diagnostic itself is better educated:

  $ set -u
  $ asdasdf
  $ echo $asdasdf
  bash: asdasdf: unbound variable


"binding" seems like a more casual term for memory pointer. I guess if people are just getting started with programming it make sense to simplify things a bit.


It's not a simplification. It is abstraction. Binding doesn't imply a particular implementation.

A variable binding can disappear entirely. If you bind var x = 42 and never use it, the variable need not exist. If it doesn't exist, then there is no pointer.

If you do use it, constant propagation/folding can again make the variable disappear. If the variable is never assigned, all uses of it can be replaced with 2.

Variables that care captured by lexical closures can be treated differently from ones that are not. Variables captured by closures but not shared among different closures, or not mutated, can be treated differently from mutated variables shared among closures.

The abstraction of binding is more complicated than "every variable is a memory pointer" because it allows more possibilities, which can coexist.


My point is that it's not a simplification, it's precisely how the language works: bindings between values and names (JavaScript has no separate notion of memory pointer; everything is a "pointer"). (Similarly for Python: https://nedbatchelder.com/text/names1.html) Describing variables in this way gives readers the correct understanding, and the analogy of tentacles is no harder than that of boxes. Such things are what I most appreciated, that the author manages to be approachable without sacrificing accuracy.


If the explanation doesn't mention memory positions then it is a simplification.


JavaScript does not provide a way for the programmer to access memory positions (and e.g. does not guarantee that the the language runtime will maintain unvarying memory positions), so it doesn't make sense to talk about memory positions: there's nothing to be gained at that level of abstraction. (Unless you'd call it a "simplification" to not talk of electrons and transistors too, in which case fine, yes it's a simplification in that sense.)




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: