-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should Records and Tuples be objects, instead of primitives? #201
Comments
Having "identity-less objects" would violate fundamental axioms of the language. If they're not primitives, I don't think they can or should ever have |
We could make |
Similarly, I do agree though that it's no big deal that boxed primitives are inequal even though the primitives are equal, since that's how everything always works. |
I want to mention a separate effect of using objects instead of primitives, which is that, by not having wrappers, the This use of direct At first, I thought that Box would be enabled specifically by using objects instead of primitives, but it turns out that that is admissible from an object-capability-security perspective regardless of object vs primitive; see #200 . So I see the extensibility concern as the main reason to consider Records and Tuples as objects, rather than primitives.
This is definitely a thought that I went into this proposal thinking, but the ideas that @rickbutton noted in this issue seem interesting to me. I think we should go back and think about why only primitives should have value-based equality semantics. To me, the underlying goals around
These invariants correspond to only comparing things that have semantics analogous to Records and Tuples or primitives by value, and comparing objects by identity and not their contents, but they don't force a primitive vs object split in particular. Maybe there are other reasons why we should be considering that there's a strong association here. It'd be helpful to hear more about what kinds of properties lead you to make the association between value-based |
If it is an object, it should allow Proxys on it. |
@Jack-Works Can you open a separate issue around Proxy with Record and Tuple as a target? It's a big area. It would be great to hear why it's important. |
I'm strongly against the idea of the identity-less object, but if it is an object, it should support Proxys cause all object supports Proxy. I think we can discuss this later if it switched to identity-less object. |
While reading the Concurrent JS Slides, it made me think about this discussion. It feels like there would be an advantage of Records & Tuples being primitives when it comes to transferring/accessing them across threads/workers/realms/module-blocks. |
I think of records/tuples as identity-less objects the same way as I think of registered symbols. The engine is creating a unique and stable identity from some forgeable user data. I don't think there is a need for some special internal slot, just for an internal lookup if a record/tuple object already exists in a global registry for a given content. |
If R&T use SameValueZero (#65) then |
I forgot about that point. As I noted today in the SES meeting, this would mean that unlike other objects, const nz = #[-0];
const pz = #[+0];
typeof nz === 'object';
nz === pz; // true
Object.is(nz, pz); // false |
I wanted to quickly clarify that with |
FYI, Java have identity-free objects (value objects) now. @mhofman Could explain more about how |
I think it's easier to explain in terms of forgeable identity, and consider that every value has an identity comparable through Like strings and numbers, records/tuples have a forgeable identity. They're unlike objects or unique symbols, which have an unforgeable identity. Since records/tuples are a structure which can contain unique symbols (and maybe in the future boxes if they are re-introduced), the identity of the record/tuple really is a composite of the structure/shape and of the unforgeable values it contains. All that to say, you can't forge the identity of a record/tuple unless you hold all the symbols/boxes that make it. |
Per the current spec and discussions in-committee, Records & Tuples will be primitives. This allows the equality semantics discussed in #65 and will make them work with the Shadow Realms proposal. |
Introduction
Records and Tuples are deeply immutable data structures that have "value semantics", i.e. they contain no mutable data, they have no identity, and they are compared by contents rather than by reference. Even though Records and Tuples look like Objects and Arrays, they behave like String or Number primitives, and are currently specified as primitives just like strings and numbers, in order to facilitate this behavior.
For example, when you compare two different objects, they are not equivalent, even though they might contain the same data:
If you compare two primitives, they are compared via their contents. Primitives don't have identity, and there isn't such a thing as an "instance" of a primitive, two primitives are either equal because they are the same, or not equal because they are different:
Because Records and Tuples have "value semantics", they behave like primitives when compared:
However, there are a few possible downsides to making Records and Tuples primitives.
When object operations are performed on primitives (property access, etc) the primitive is "wrapped" in an exotic wrapper object that implements those object behaviors. This is usually not noticed, because the wrapper isn't observed, for example:
However, if a primitive is wrapped unexpectedly, it can cause problems:
Even though both
a
andb
point to the number42
, they are both instances of theNumber
exotic wrapper object. Because these are objects, they have identity, and are compared by said identity, not their primitive contents. This also applies to primitive records:Even though
a
andb
point to records with the same contents, they are not equal because instances of theRecord
exotic wrapper have identity.Identity-less objects?
Instead of defining Records and Tuples as primitives, we could instead define them as "identity-less objects", or an object without identity. An object without identity might be an object with an internal slot marking it as such an object. When identity-less objects are compared, they are compared by contents, not by identity. Records and Tuples as identity-less objects would have these properties:
Given the above properties, Records and Tuples as "identity-less" objects behave in the same way as primitive Records and Tuples, except that they don't require wrappers. This simplifies the model for Records and Tuples, and means that engines don't need to optimize them out where possible (like they do for existing primitives).
Open Questions
Is "identity-less" objects the right approach for describing the behavior of Records and Tuples?
How are "identity-less" objects differentiated from regular objects? A special internal slot?
What should
typeof
return for "identity-less" objects?object
?The text was updated successfully, but these errors were encountered: