<div dir="ltr"><div>I'll preface this by saying that I haven't made a formal proposal and this isn't an actual library. You're doing a good job of spotting some undefined behavior which would probably be better defined by trying it out. I'll give my opinions on them, but it could all use a good test drive before coming down on these.</div>
<div><br></div><div>To help the discussion I'll paste the basic algorithm I outlined:</div><div><br></div>1. if the receiver has an own property of the same name, use that<div>2. if the receiver's type matches an extension of the protocol, use the protocol method</div>
<div>3. if the receiver has a method of the same name somewhere up the prototype chain, use that</div><div>4. use the default if available</div><div><br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div><br></div><div>----- Case 1:</div><div><br></div><div>I have an object O of type Foo. A protocol P.</div><div><br></div><div> - O has the structure {x:5,foo:7};</div>

<div> - The protocol implements `foo` but does not specifically for Foo (via .defaults). </div><div><br></div><div>What happens? Does `P.foo` get invoked, or do we get an error because `O.foo` is not a function?</div></div>
</blockquote><div><br></div><div>I can see most of your examples involve the interaction between the protocol method and a method supplied on the object itself. Clojure protocols don't have this type of interaction. I tossed them in because they seemed like they would work well with some of the examples brought up in the other thread. They definitely complicate things... I guess I would say that I would have this throw an error. Logically to me, either the an error should be thrown because it would try to invoke foo on the object, or we should give up on the idea of falling back on the object. Skipping foo on the object because its not a function seems too magical.</div>
<div><br></div><div>So here, O has an own property, so #1 and blows up</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div>

<br></div><div>---- Case 2:</div><div><br></div><div><div>I have an object O of type Foo, Foo.prototype = new Bar. A protocol P.</div><div><br></div><div><div> - O has the structure {x:5,foo:7};</div><div> - The protocol implements `foo` for Bar specifically (but not for Foo)</div>


</div><div><br></div><div>What happens?  (Similar to case above?)</div></div></div></blockquote><div><br></div><div>Same as above - error (or drop the feature)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div><div><br></div><div>---- Case 3:</div><div><br></div><div><div>I have an object O of type Foo, Foo.prototype = new Bar. A protocol P.</div><div><br></div>

<div><div> - O has the structure {x:5,y:7};</div><div> - Bar has a method foo</div><div> - The protocol implements `foo` for Bar specifically (but not for Foo)</div></div><div><br></div><div>What happens? Does it invoke Bar.foo or P.foo?</div>
</div></div></div></blockquote><div><br></div><div>Ah, yes, I had thought about this a bit, but it had never made it into my gist at all. Let me revise my algorithm:</div><div>    4. Check up type chain for match</div><div>
    5. If method defined on protocol default, use that</div><div>    6. Otherwise error</div><div><br></div><div>1. false, continue</div><div>2. false, continue</div><div>3. false, continue</div><div>4. true - use Bar.foo</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><div>

</div><div><br></div><div><div>---- Case 4:</div><div><br></div><div><div>I have an object O of type Foo, Foo.prototype = new Bar. A protocol P.</div><div><br></div><div><div> - O has the structure {x:5,y:7};</div><div> - Bar has a method foo</div>


<div> - The protocol implements `foo` for Bar specifically (but not for Foo)</div></div><div><br></div><div>What happens? Does it invoke Bar.foo or P.foo ?</div></div></div></div></div></blockquote><div><br></div><div>This looks the same as 3 to me, so Bar.foo</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><div><br></div><div><div>---- Case 5:</div>
</div>

<div><br></div><div>I have an object O of type Foo, I import two `Protocol`s that implement a method `Foo` at the same specificity level - what happens?</div></div></div></blockquote><div><br></div><div>This is an easy one and comes down to the benefits of making use of normal variables and lexical scoping. Remember that protocols don't affect the types at all, and the protocols exist completely independently of each other. If you imported two protocols A and B that each have a method 'foo' defined for type Foo, the only thing you would have to be careful of is redefining your variables accidentally.</div>
<div><br></div><div><div>    import {foo} from 'A';</div><div>    import {foo} from 'B';</div></div><div><br></div><div>This is going to be a problem no matter what you're doing. You are importing two things with the same name, trying to introduce to variables with the same name. There's no magic for protocols here, you can just alias your imports to avoid name clashes.</div>
<div><br></div><div><div>    import {foo as fooA} from 'A';</div><div>    import {foo as fooB} from 'B';</div><div>    </div><div>    o::fooA();</div><div>    o::fooB();</div></div><div><br></div><div>Alternatively, if the have the protocol itself, you can access the methods directly and do:</div>
<div><br></div><div><div>    o::A.methods.foo();</div><div>    o::B.methods.foo();</div></div><div><br></div><div>Which isn't as nice, but is an option.</div><div><br></div><div>- Russ</div></div></div></div></div>