need some clarification on compile-time type vs. run-time type

Brendan Eich brendan at
Sat Nov 10 22:50:03 PST 2007

On Nov 10, 2007, at 9:57 PM, Brendan Eich wrote:

> If I understand your point, it's that if we allow
>    (a is T)
> given a type name T bound by a type, class, or interface definition;
> but we disallow
>    let (t = T) (a is t)
> and insist on
>    let (t = T) (a is type t)

Make that

   let (t = type T) (a is type t)

But even that doesn't work. I forgot an agreement from the September  
face-to-face meeting, to make 'is' less future-hostile to an "ES5"  
that merges type and value expressions somehow: change 'is' to insist  
on a type expression only, therefore not including the unary 'type E'  

This results in the current RI's behavior, modulo that bug where  
'type T' => null (those FIXME comments in eval.sml):

 >> type T = {p:int}
 >> let t = T
[locn] /Users/brendaneich/Hacking/es4/com.mozilla.es4.smlnj/builtins/
[stack] [init t()]
**ERROR** EvalError: uncaught exception: TypeError: getValue on a  
type property: <public >::T  (near /Users/brendaneich/Hacking/es4/ 
 >> let t = type T
 >> t
 >> o = {p:42}
[object Object]
 >> o is T
 >> q = {p:42}:T
[object Object]
 >> q is T
 >> q is t
**ERROR** VerifyError: expected type fixture for: [[<public >,  
<internal >], [<public __ES4__>]]::t (near <no filename>:1:2-1.1)  
while normalizing <TypeName: {(<public >, <internal >), (<public  
__ES4__>)}::t> (near <no filename>:1:2-1.1)
 >> q is type t
**ERROR** ParseError: expecting semicolon before identifier(t) (near  
<no filename>:1:2-1.1)
 >> q is (type t)
**ERROR** ParseError: unknown token in unionType (near <no filename>: 

See, 'is' won't even begin to parse 'type t' or parenthesized  
(union!) forms of same. The RI bug that made t null doesn't matter.

> The issues are (AFAIK):
> * Should instanceof do its loosey-goosey ES3 thing for functions,
> which have mutable .prototype, and mix this backward-compatible
> feature into different-in-many-ways subtype tests done by 'is'-as-
> proposed?

My current thinking is "no" but I'd like to think more.

> * Should 'is' insist on fixed type name in its right operand, or is
> this inconsistent and pointless, an RI bug even?

So it's not an RI bug (ignoring the lack of meta-object hookup). It's  
intentional future-proofing against the day when merging type and  
value expressions (somehow!) is upon us. Which you've expedited! ;-)

If we allow a value expression on the right of 'is', the only  
syntactic ambiguities are structural type expressions:

record:   {p:int, q:string}
array:    [boolean, double, string]
union:    (undefined, string)
function: function (A,B):C /* no body, I'm a type */

Requiring these to be prefixed by unary 'type' and committing to the  
consequences (no strict-mode checking of 'is' by fancy, even  
conservative analyses; no future where we merge type and value  
expressions differently) does seem better to me. But I'm forgetting  
something from that September meeting, maybe. Checking minutes... 

Ticket 103:

Seems the resolution ruled narrowly by pointing to meta-objects, as  
I've done a couple of times in this thread. But the big picture  
confusion you point out, that users expect dyadic operators to take  
value expression operands, and that fixed type names vs. other names,  
even well-bound let variable names (let const even!) can't be used on  
the right of 'is', seems not to have been considered.

If I nerd out over types, yeah: is/cast/wrap all take a right operand  
which must be a type expression. Get used to it, poindexter! ;-) But  
really, it's a bit harsh and anti-JS to say this, for 'is' at any  
rate. Possibly the verb is too short and overloaded. More work  
needed, I think.


More information about the Es4-discuss mailing list