On 07.10.2010 22:21, Tom Van Cutsem wrote:
Hi Dmitry,

    Hi MarkM and Tom, possibly it will be interesting to you:
    http://gist.github.com/613924 -- a delegation based mixins
    implemented using Harmony proxies.

    Features:

      - working in two modes: traits (naming conflict predicting at
    early stage), or simple linearization (mixins mode, there is no
    warning about naming conflicts);

      - "in" operator is working on object (e.g. /"foo" in bar/ is
    /true/ if either /bar/ has own property "foo", or any of mixed
    objects have the property (including consideration of their
    prototype and mixin chains), or if the property is found in the
    prototype chain of the /bar/).

    Cons: possible overhead on reading / or testing for "in". Should
    be avoided at lower level implementation.

    TODO: syntactic sugar (possibly for CoffeeScript).


It's an interesting experiment. On first sight, your inheritance mechanism looks very similar to Ruby's modules.

Yes, Ruby also uses hidden proxy-class to communicate with a mixin module.

Although one big difference is that in your experiment, your mixins can also have their own prototype chain (IIRC in Ruby, modules can't inherit).

Yeah, not for user-defined inheritance. But modules there inherit though form some general built-in classes (i.e. Object, BasicObject, Class, etc).

I think that may be a bit too flexible, leading to even more complex lookups than is the case with multiple inheritance. If you would ignore the prototype of the mixins, you end up with something called "comb inheritance" (at each level, check the object and the mixins horizontally, if not found go up one level on the prototype chain and try again) which is a bit more tractable for programmers to deal with, I think.


Yes, such implementation is also possible. Moreover, implementation is very easy -- /Module.new/ will be just /Object.create(null)/. On the other hand, it's not required to be a complete clone of Ruby's modules. It may be better, though ;) But it prototypes of modules bring inconvenience and confusion, I'll make them prototype-less.

Your experiment does show that it's possible to combine conflict detection + delegation to some extend. However, I wouldn't call your conflict detection mode "trait mode".

Of course, because it's a similar to Ruby's module system though -- with liniarization, but not traits in respect of conflict predicting; I added "traitsMode" just to enable this small ability to warning an issue. And again, backing to classical traits, e.g. Ruby's Enumerable module -- is a trait: (1) it doesn't not have a state, (2) it does not break the state of classes/objects to which it mixied/include and (3) it does brings additional functionality based on the sate of an object (possibly, state provided by the class definition -- including needed methods and properties). And that this system does not provide naming conflict detection -- well, it's just one of possible implementations. It choosen linearzation though, to keep dynamics and reusing. I combined it providing a very basic of naming conflict detection.

First: the system is not conflict-proof: if some code adds a property to a mixin object or to the target object at a later point in time, potential conflicts will go undetected.

Theoretically it's possible to implement (e.g. store for a module list of objects/classes to which it included, and trap all [[Set]] generic set with checking, whether the new name is in some object. The same for objects). But practically it will be unnecessary overhead.

Second, even in "trait mode" the ordering of the mixins matters (trait composition is commutative, ordering is not important, at any level of composition).

Of course, if a composed (from several /static/ modules/traits/mixins) "holy" object has /all/ of those properties/methods as /own/, the order is not essential. But if to consider exactly reusing of the code, with inheritance, the order does matter. Also, since you freeze your traits, it moves to statics anyway (hello, Java) and you can't extend a trait anyway -- yeah, no extension, no problem with later naming conflict detection.

Third, there seems to be no obvious way to resolve/avoid a signaled conflict (traits have aliasing or overriding to deal with this).


    P.S.: it's good to have /noopHandler/ for proxies as a built-in
    function, it's a useful sugar (possibly even to make it as a
    default handler (if some handler's properties are not specified),
    though it may be unnecessary overhead).


Yes, I agree! We've talked about this in the past but haven't yet settled on a standard API. Perhaps we should.
I think Proxy.noopHandler(target) may be a bit obscure. Other suggestions:
Proxy.createHandler(target)
Proxy.forward(target)
Proxy.handle(target)

Yeah, also good names, I just used /noopHandler/ as first came to mind, since the section of the proxies article is called the same.

    P.S.[2]: proxies are nice ;)


Thanks! Keep on experimenting :-)


Yes, I do. The latest is "magic methods" directly on objects (possibly you saw -- http://gist.github.com/617338; I don't know what again with es-archive server, but it doesn't display the lettter which I send about "get+fn vs. invoke" -- https://mail.mozilla.org/pipermail/es-discuss/2010-October/thread.html -- there only answer on the letter with correcting the typo).

Maybe you can answer on this question regarding proxies? How can we handler in one /get/ of a proxy handler both cases of a call-site:

foo.bar

and

foo.bar()

?

Having /invoke/, we handler foo.bar(). However, the case when the /get/ returns should look (unfortunatelly?) like (foo.bar)(). Also of course foo.bar does not extracted as a functional object (including invariants foo.bar.call/apply). But I think, is it the case that user wants to used them exactly as funargs or he wants more to handle just access (exactly /calling/ of) to non-existing methods? P.S.: to avoid off-topic regarding this topic devoted to traits/mixins, it's better to answer to that trhead -- "get+fn vs. invoke"/.

/
Cheers,
Tom

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

Reply via email to