Ecma262: Clarification required that Lists are 'referency'

Created on 9 Dec 2016  ·  14Comments  ·  Source: tc39/ecma262

In 8.1.1.4.7 Global Environment Records DeleteBinding(N) step 7b, varNames is assigned the List value from envNames.[[VarNames]]. Subsequently varNames has an element removed. The algorithm does not explicitly propagate this value back to the envNames record.

It can then be inferred that Lists should be treated as being 'reference-like' when referred to, as opposed to being 'value-like' as in some other languages.

I have re-checked the Types and Algorithmic Conventions sections and couldn't find text explicitly supporting this interpretation.

Would it be a helpful addition to the spec to clarify this in the Types section? I'm happy to raise a PR.

Most helpful comment

I'd like to add the following to algorithm conventions:

Algorithm steps may declare named aliases for any value using the form “Let x be someValue”. These aliases are reference-like in that both x and someValue refer to the same underlying data and modifications to either are visible to both. Algorithm steps that want to avoid this reference-like behavior should explicitly make a copy of the right-hand side: “Let x be a copy of someValue” creates a copy of someValue.

All 14 comments

I always assumed they were reference-like. I wouldn't mind clarifying text that everything in the spec is reference-like, and nothing at all is value-like, or the text could be restricted to specification types like this. Any thoughts @allenwb ?

I've been programming in Haskell and OCaml too much where everything is explicitly value-like unless otherwise specified. As a result of that, my default behaviour was to read mutation operations on value-like lists as mutating the value and reassigning to the variable, my intuition only tripped when the reassignment to the local variable would have no overall effect.

I had a brief grep look through the ES5 spec for List mutations, and was interested to note that it didn't matter there whether Lists were treated as value-like or reference-like there as the results would be the same either way.

Records, Objects are nearly always treated as reference-like in the spec, as the text usually says "update the x field of y" making them less likely to cause a trip. Although not declared as a specification type, the Execution Context Stack is also clearly reference-like as it is global to the specification.
I believe (from a quick search) that the Reference Specification Type itself can be value-like, as it seems to be immutable after construction, similarly Symbols can be value-like as their only field is immutable.
It seems that in most cases [citation needed] Strings are treated as values, although I have found one instance of a String being treated as a reference-like type.
(And null, undefined, booleans and numbers are clearly pure values).

(Yes, I am in pedantic mode).

In Haskell and OCaml, everything is by reference. Many objects are immutable (or all in Haskell), but there isn't conceptual copying happening all the time as in Swift and C++. It's just that idioms often encourage operations to return new objects.

In the ES spec, no new object is being created. Often, lists aren't mutated, but when they are, you're mutating the original one. IMO the spec is already clear enough, but it wouldn't hurt to have a clarifying note to explain that the mental model is not that of C++/Swift with copying.

Agreed it's by reference when compiled, I was referring to the conceptual level of the language, but we're now off topic :smile:

I think we're agreed on the clarifying note then, I'll draft it up for review.

Lists are a flexible mechanism of the relatively informal specification notation. Different use cases may have slightly different semantics (or example, ordered vs unordered, mutable vs immutable) that should be clear from each usage context. Most usages can be thought of as reference-like (or equivalently, the pseudo-code "let" operation can be thought of as a "by name" aliasing of its RHS). Because List mutability is common, I tried to always be explicit about when a new copy of a List was needed.

This informality seems to generally be adequate for human interpretation of the spec. Any effort to formalize the spec. or to perform mechanical analysis would probably need to replace List with somethings that were less informal.

@allenwb Even though lists are used in various different ways, I think it's in common among all uses that there is no implicit copying of them when they're passed around. Would it be bad to add some wording to clarify this?

I'd like to add the following to algorithm conventions:

Algorithm steps may declare named aliases for any value using the form “Let x be someValue”. These aliases are reference-like in that both x and someValue refer to the same underlying data and modifications to either are visible to both. Algorithm steps that want to avoid this reference-like behavior should explicitly make a copy of the right-hand side: “Let x be a copy of someValue” creates a copy of someValue.

+1 to @bterlson's language. I like how it applies to all objects--nothing is specifical about lists.

I can't lose this pedantry contest, so here's a new tangential point: Should we make it clear that 'a copy' refers to a shallow copy somehow? Maybe 'a copy' should be an operation on spec types specifically. Almost all usages are on spec records (if that includes property descriptors and environments) or lists, except for String.prototype.trim which could be reworded. If 'a copy' is restricted to spec types, it is easier to understand what it means to be shallow.

Seems good to specify that it's a shallow copy. Perhaps it's enough to simply insert "shallow":

Algorithm steps that want to avoid this reference-like behavior should explicitly make a copy of the right-hand side: “Let x be a copy of someValue” creates a shallow copy of someValue.

How about omitting the copy stuff altogether? It's not needed anywhere, right? And I'd expect it to be fully defined with algorithms for creating a new List/Record/etc. if we did use it.

What does copy stuff refer to?

"Algorithm steps that want to avoid this reference-like behavior..."

Previously, "a copy" wasn't defined anywhere, but it was used in several places, so I like that this suggested text defines it.

Talked to Domenic offline, we think these changes are fine :) I'll commit.

Was this page helpful?
0 / 5 - 0 ratings