struct

# Sam Ruby (16 years ago)

At the last meeting, Mark Miller committed to explore creating a proposal involving double-dispatch and value types. Upon reflection, I remembered that ECMA 334 defines "struct":

en.csharp-online.net/ECMA-334:_18._Structs

Without delving into syntax, though I do note that "struct" is not a reserved word in ECMAScript, this type of concept does seem to address the basic requirements that Mark was going to pursue, and additionally addresses some of the secondary characteristics (such as not necessarily requiring heap allocation) that Brendan alluded to in the discussion.

Independent of any discussion of predefined numeric types, I believe that there is a class of performance critical applications that could benefit from an introduction of "structs" into ES. Additionally, such an addition could make ES more attractive as a compilation target (I say while glancing meaningfully in the direction of Allen).

Since implementations will be free to (but not required to) copy the value instead of the reference, it is important that the triple equals operator compares the values for struct types. Double equals can implement different semantics.

Taking Rational as an example, the following makes sense to me. Anybody differ?

Rational(2,1) == 2 ==> true Rational(1,2) == Rational(2,4) ==> true Rational(2,1) === 2 ==> false Rational(1,2) === Rational(2,4) ==> false

Given the above, the answer to the below is less clear:

foo = {} foo[Rational(4,2)]='a' foo[Rational(2,1)]='b' foo[2]='c'

foo[Rational(2,1)] ==> 'b' ??? foo[Rational(4,2)] ==> 'a' ???

The motivation for the above is the question of whether or not there will be the possibility of any user visible cohorts.

Double dispatch also provides an opportunity to mitigate the usability problem that Brendan often laments. While the Rational package can provide a default implementation for a set of operator overloads (I'll note that every double precision binary floating number has an exact representation in terms of a rational number, something that is not true in reverse), users that desire different behavior can simply replace these operators. This could even be done globally (a big red switch, as Brendan seems to prefer).

The syntax question remains open, particularly for literals.

  • Sam Ruby
# Mark S. Miller (16 years ago)

On Tue, Jun 9, 2009 at 11:05 AM, Sam Ruby <rubys at intertwingly.net> wrote:

en.csharp-online.net/ECMA-334:_18._Structs

Hi Sam, thanks for the pointer. I will read.

Taking Rational as an example, the following makes sense to me. Anybody

differ?

Rational(2,1) == 2 ==> true Rational(1,2) == Rational(2,4) ==> true Rational(2,1) === 2 ==> false Rational(1,2) === Rational(2,4) ==> false

Rational's may be a bad example, because if I were implementing them, they'd always reduce to canonical form on construction so my last result above would be "true". However, in the spirit of your question, we can suppose a Rational representation which doesn't auto-canonicalize. In that case I agree with these outcomes.

Given the above, the answer to the below is less clear:

foo = {} foo[Rational(4,2)]='a' foo[Rational(2,1)]='b' foo[2]='c'

foo[Rational(2,1)] ==> 'b' ??? foo[Rational(4,2)] ==> 'a' ???

Since Rational, being a struct, can overload operators (other than ===, !==, &&, ||, and ?:), then your second case should be equivalent to

Rational(4,2)'reverse[]'

The motivation for the above is the question of whether or not there will be the possibility of any user visible cohorts.

User visible cohorts do not violate any principle associated with structs and operator overloading. Indeed, it is impossible for such an extensible framework to prevent library authors from introducing such types themselves. Whether we want to standardize a numeric type with this behavior is another matter. I don't. That's one of the reasons I'd build Rationals that auto-canonicalize.

# David-Sarah Hopwood (16 years ago)

Sam Ruby wrote:

Independent of any discussion of predefined numeric types, I believe that there is a class of performance critical applications that could benefit from an introduction of "structs" into ES. Additionally, such an addition could make ES more attractive as a compilation target (I say while glancing meaningfully in the direction of Allen).

I agree.

Since implementations will be free to (but not required to) copy the value instead of the reference, it is important that the triple equals operator compares the values for struct types.

Yes. === should behave like SameValue, with NaN !== NaN and 0 === -0 as the only exceptions. SameValue should behave like Henry Baker's 'egal'.

Given the above, the answer to the below is less clear:

foo = {} foo[Rational(4,2)]='a' foo[Rational(2,1)]='b' foo[2]='c'

foo[Rational(2,1)] ==> 'b' ??? foo[Rational(4,2)] ==> 'a' ???

The property position of the [_] operator is coerced by ToString in ES3/5. For struct types to behave differently would be irregular. (Even if this coercion was not a good idea in the first place, creating exceptions to it does not really help.)

So if ToString(Rational(4,2)) === ToString(Rational(2,1)) === '2', then these references would all alias the '2' property of foo.

The motivation for the above is the question of whether or not there will be the possibility of any user visible cohorts.

I'm with MarkM on this -- it is impossible to prevent a user-defined type from having cohorts, but desirable not to standardize any type that does.

Double dispatch also provides an opportunity to mitigate the usability problem that Brendan often laments. While the Rational package can provide a default implementation for a set of operator overloads (I'll note that every double precision binary floating number has an exact representation in terms of a rational number, something that is not true in reverse), users that desire different behavior can simply replace these operators. This could even be done globally (a big red switch, as Brendan seems to prefer).

It should be done within a specified lexical scope. I'll post a proposal for that at some point (not soon since I'm concentrating on ES5 and Jacaranda at the moment).