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

Brendan Eich brendan at mozilla.org
Sat Nov 10 19:27:56 PST 2007


See http://bugs.ecmascript.org/ticket/248 -- the meta objects proposal:

http://wiki.ecmascript.org/doku.php?id=proposals:meta_objects

used intrinsic, but as #248 notes, there are good reasons for putting  
the meta-objects functions and types in their own namespace:

     * intrinsic should mean "early bindable, generally useful"
     * meta is reserved for hooks (and that seems like a good thing)
     * iterator is used for all the iteration stuff
     * uint32ops is used for uint operators
     * reflect is a good name for reflection
     * partitioning the methods means that we can have reflection  
methods on various kinds of objects without worrying about name  
clashes (e.g., reflect::construct could in principle be a method on a  
class object, so class objects could implement ClassType directly --  
this is possible at present, but if so precludes adding an  
instrinsic::construct method to the class object for other purposes  
in the future)

The last point is significant.

/be

On Nov 10, 2007, at 7:19 PM, Michael O'Brien wrote:

> Brendan,
>
> I didn't see the reflect namespace documented in the overview.
>
> Can you please provide some pointers to its doc?
>
> Michael
>
> Brendan Eich wrote:
>> On Nov 9, 2007, at 5:29 PM, Yuh-Ruey Chen wrote:
>>
>>
>>> The confusion I'm getting is that there seems to be many ways to  
>>> check
>>> or differentiate between types. For example, consider the following
>>> ES3
>>> function:
>>>
>>> function foo(x, t) {
>>>     if (!(x instanceof t))
>>>         throw some_type_error;
>>>     print(x);
>>> }
>>>
>>> If t were a fixed type property, then foo could be redefined as:
>>>
>>> function foo.(x) {
>>>     if (!(x is t))
>>>        throw some_type_error;
>>>     print(x);
>>> }
>>>
>> Here t is the name of a type parameter to foo, so it is by definition
>> fixed -- it doesn't matter how you instantiate foo. for some T --
>> but there again, in the foo. expression, you need a fixed type
>> term T.
>>
>>
>>> Or maybe the following is possible (it's currently disallowed in
>>> the RI):
>>>
>>> function foo.(x: t) {
>>>     print(x);
>>> }
>>>
>> I'll let Graydon reply in full, and give an update -- I heard he
>> nearly has type params working.
>>
>>
>>> Which one is preferred in ES4? The ES3 version is more flexible in a
>>> way, since it treats types as first-class values,
>>>
>> A constructor function is not a type in ES1-3, it's a function
>> object, which if user-defined has a completely writable prototype
>> property that instanceof checks. So it is not bad (or good), but I'm
>> here to say: it's not about types in the ES4 sense.
>>
>> Indeed user-defined constructor functions all make Object instances,
>> by definition, although you could strengthen them to make structural
>> subtypes of Object in ES4:
>>
>> function MyConstructor(a, b) {
>>      return {a: a, b: b} : {a: int, b: string};
>> }
>>
>>
>>> but the last version
>>> is the most efficient. Users will have to deal with this choice,
>>> but it
>>> requires a decent understanding of the type system to make a good
>>> choice.
>>>
>> Users can buy by the yard. The old ways work for the dynamic
>> constructor/prototype world everyone knows.
>>
>> Above you have made three different things. The instanceof check is
>> not the same as the |is| check. The type paramter example is yet
>> again different -- it's just printing x assuming x is compatible with
>> t -- that is, that there's no type error on attempt to call foo.,
>> e.g. foo.(new RegExp).
>>
>>
>>> And it doesn't end there. I haven't even addressed the |is like|
>>> compound operator,
>>>
>> It's not a compound operator: 'like' is a type constructor or type
>> unary operator if you prefer: like T is a type, you can use it
>> freely. Thus because (x is T) can be tested, and T can be defined as
>> like U, you can write (x is like U). Make sense?
>>
>>
>>> of which there is no counterpart in |instanceof|
>>> since structural types apparently can't be stored as non-fixed type
>>> properties (|type x={a:int};y=x;| doesn't work in the RI).
>>>
>> Type are types, not functions; the instanceof right operand is a
>> *function* per ES1-3 and backward compatibility.
>>
>>
>>> I'm not sure how to phrase this, but it seems to me that ES4 is  
>>> trying
>>> to make fixed properties and non-fixed properties (and by extension,
>>> type expressions and value expressions, and compile-time features  
>>> and
>>> run-time features) as similar and compatible as possible (e.g. | 
>>> 10 is
>>> int| and |10 instanceof int|), yet there are evidently many cases
>>> where
>>> they can't be interchanged (e.g. my first example).
>>>
>> I think you are mixing up fixed and non-fixed properties with types
>> and functions.
>>
>>
>>> I know from
>>> experience that the more similar concepts get, the higher the
>>> potential
>>> for confusion, until they become the one and the same. And the two
>>> concepts in question here cannot be one and the same if we want  
>>> ES4 to
>>> support efficient compilation. Perhaps, to reduce the confusion, the
>>> differences between the two can be more pronounced, either through
>>> syntax and/or behavior. I don't have any specific suggestions  
>>> though.
>>>
>> Here's what should work:
>>
>> 10 is int => true
>> 10 instanceof int => true
>> type T = int
>> 10 is T => true
>> 10 instanceof T => true
>>
>> No confusion, so far (IIRC the RI has a bug on the last line, but
>> let's assume it is fixed). Now:
>>
>> let U = int
>> 10 instanceof U => true
>> 10 is U => error
>>
>> Using a const (or let const) does not help here, only type will do.
>>
>>
>>> At the very least, the differences and similarities need to be
>>> fully and
>>> carefully documented. ES3 already has plenty of gotchas, and ES4  
>>> seems
>>> to be introducing plenty more.
>>>
>> It's true that ES4 is introducing optional types. But remember,
>> they're optiona. You don't have to use them, but if you choose to,
>> you need to follow the rules about using type definitions or
>> equivalent (class, interface) to make bindings that are fixed  
>> typenames.
>>
>> One escape hatch is to use reflection, which looks something like
>>
>> {
>>      use namespace reflect
>>      print(typeOf(10).isSubtypeOf(U))
>> }
>>
>> That's not working for me in the RI, and I may have misremembered a
>> method name. Graydon knows best.
>>
>> /be
>>
>> _______________________________________________
>> Es4-discuss mailing list
>> Es4-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es4-discuss
>>
>>
> _______________________________________________
> Es4-discuss mailing list
> Es4-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es4-discuss

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20071110/310a33da/attachment-0002.html 


More information about the Es4-discuss mailing list