typed objects and value types

Mark S. Miller erights at google.com
Wed Apr 2 11:26:31 PDT 2014

On Wed, Apr 2, 2014 at 10:37 AM, Niko Matsakis <niko at alum.mit.edu> wrote:

> > I think the idea that value types should be objects would
> > require stretching the notion of object too far, and violate one of
> > the fundamental properties that objects currently have.
> Certainly this was the idea, though I didn't think of it is as
> violating, but rather... stretching. :)

I find your arguments about why uvalues can't simply be an extension of
primitive values convincing. I find Andreas' arguments about why uvalues
can't simply be new kinds of objects convincing.

Although I am *not* suggesting that we import the entire taxonomy used by
E, it can help inform the discussion. It is shown by the diagram at <
http://erights.org/elang/kernel/auditors/images/prop-tree.gif> within <
http://erights.org/elang/kernel/auditors/>. (Note that this paper is stale
regarding E itself, but is still probably the best starting point for
understanding the distinctions we might want to borrow into JS.) Depending
of whether uvalues may or may not contain non-uvalue objects, uvalues
correspond either to E's PassByCopy or DeepPassByCopy.

The key point for the current discussion is that both are Selfless, i.e.,
identity-free, and compare for equality based purely on internal structure.
They are also Transparent, which means "non-encapsulating" in the sense of
being reproducible purely from client visible data, which is distinct from
the implementation-level "opaque" notion your typed objects article.

Together, these ensure that, for a deep uvalue x,

    x === unserialize(serialize(x))

for some suitable serialization into a pure data form. This allows deep
uvalues to be passed between vats either by copying or by pointer sharing
at the implementation's choice, without any observable difference. Between
vats within an address space passing by pointer sharing is important for
performance. Between vats in different address spaces or on different
machines, copying is necessary. It's nice that this difference can be made
non-semantic, but see below.

> > Other properties, like the ability to use an object as keys in weak
> > collections, follow from that. If we suddenly allowed objects that do
> > not have identity, but a structural notion of equality, then we could
> > not allow these objects into weak collections.
> Interesting point. I hadn't thought about weakmaps (though it seems
> like an obvious next step from thinking about *maps* in general).

Maps and Sets can already use non-identity values as keys with structural
equality, i.e., the current primitive values. Thus, Maps and Sets should be
able to use uvalues as well.

WeakMaps cannot use uvalues as keys for the same reason they can't use the
current primitive values.

We could specify that WeakMaps can use typed objects as keys. The current
discussion in your article confuses semantics with implementation when it
speaks of typed objects comparing structurally. Typed objects have
identity, characterized by the four-tuple you explain. Just as all the bits
of a thin pointer are significant when comparing two thin pointers to see
if they point at the same semantic object identity, so are all the bits in
your fat pointer significant. Don't get confused by the bits in the pointer
to the fat pointer, when the fat pointer happens to be boxed.

> > Either way, I think we should refrain from introducing a completely
> > new, hybrid form of value that behaves neither like a primitive nor
> > like a proper object.

Whatever words we use, the concept we're all trying to define here has some
things in common with the current primitive values, and some things in
common with current objects.

> I will ponder this for a bit and write another e-mail shortly. :) I
> want to try and draw up what I see as the family of alternatives. I
> feel like to some extent the question of "primitive or object?" is
> perhaps a distraction, though I made it sort of central to the blog
> post for some reason. The real question is to derive the properties
> that user-defined values must have, and then we can see whether it
> seems to fit better into the system as a whole to stretch primitives
> or to stretch values.
> Along those lines, user-defined values (uvalues) probably ought to
> have the following characteristics:
> - uvalues are (shallowly) immutable

+1. Whether they are shallow or not, or even whether this question extends
the taxonomy, is important to discuss further.

> - uvalues have no "generative identity", and are compared using "by-value"
> ===


> - uvalues have a prototype linked to their def'n
>   - the syntax 'uvalue.foo' can be used to access members of this prototype


>   - when transmitted between realms, uvalues retain this link

A uvalue is deeply uvalue only when its prototype and all the methods found
there are uvalues. Although this is the case for E, the implications for JS
are, ahem, tricky. If they're not deep in this way, then they can't be
passed transparently between vats, address spaces, and machines.

> - uvalues cannot go into weak maps, but can go into other maps/sets


> Does this sound about right?
> Clearly I left open the question of what typeof yields (which I don't
> feel *especially* strongly about, actually, I don't have much intution
> for what `typeof` *means* to people) and whether `uvalue.foo` works
> via a wrapper or some other mechanism.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140402/d9ee2829/attachment.html>

More information about the es-discuss mailing list