On Oct 1, 2012, at 10:37 PM, Brendan Eich wrote:

> Brendan Eich wrote:
>> But if we have a solid branding mechanism (like Domado's ideal in latest 
>> browsers? ;-) then that should be used universally and this becomes a 
>> don't-care. 
> 
> Just to be crystal clear:
> 
> * in pre-ES6 browsers, no @@toStringTag in the language to hack around with. 
> 
> * in ES6+ browsers, the better branding mechanism and @toStringTag (one @) as 
> public symbol, no worries.
> 
> Yes, this makes a fork in JS code that wants to do tag testing. Old code must 
> use O_p_toString_call (original value of, safe call binding) and string 
> compare. New code wants the better and universal scheme.
> 
> /be
> 

Yes, exactly what I envision.  New code that needs to do branding should do it 
in a new way.  But I still think we need to protect the integrity of the old 
mechanism in the presence of @@toStringTag.

It is also probably worthwhile taking a look at how internal branding is done 
in the draft spec. for Map.

We also need to be careful about making a branding mechanism too prominent.  If 
we do, too many people will misuse it as a poor man's nominal type system when 
they really should be doing behavior typing (or even more likely no explicit 
type checking at all).  Past experience is that excessive class brand checking 
is an anti-pattern for dynamic OO languages.

I think we have all the language features need to do reliable branding by ES 
programmers where they need it.  We just need to establish the patterns for 
doing that. Here is the one I propose:

private @FooBrand;
class Foo {
   constructor() {
        /* establish the internal Fooness of the instance */
        this.@FooBrand = true;
   }
}
Foo.isFoo = function (obj) {return !!obj.@FooBrand};


private @BarBrand;
class Bar extends Foo {
   constructor() {
        super();
        /* establish the internal Barness of the instance */
        this.@BarBrand = true;
   }
}
Bar.isBar = function (obj) {return !!obj.@BarBrand};

Note that an instance of Bar will be true for both Foo.isFoo and Bar.isBar

This  pattern is fine as long as it is ok that anything processed by the Foo or 
Bar constructor gets branded because not, anybody can do:
   let myFoo = Foo.call({ });

If you really need to strongly tie instantiation with branding you probably 
have to use a factory function:

module Fooishness {
   export function FooFactory ( ){return  new Foo};
   FooFactory.isFoo = function (obj) {return !!obj.@FooBrand};

   private @FooBrand;
   class Foo {
      constructor() {
           /* establish the internal Fooness of the instance */
           this.@FooBrand = true;
      }
   }
}

Allen




_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to