On 2009-Oct-14, at 8:52 am, Ovid wrote:
--- On Wed, 14/10/09, Jon Lang <datawea...@gmail.com> wrote:
The initial possibility that springs to mind would be to use longnames to disambiguate between the two options - specifically, by means of the invocant: ...or something to that effect. You'd still have a disambiguation issue, in that you'd somehow need to specify which "hat" an object of class C is wearing when you try to call the method.

Good, that's what I was looking for the last time this came up. (http://www.nntp.perl.org/group/perl.perl6.language/2009/07/msg32164.html )

Except that if a consumer of C needs foo(), they have to fully qualify the call to foo(). That violates encapsulation.

I don't see that as an encapsulation problem. A leaky encapsulation means we have to know how something works, but when I have to distinguish between $dogwood.Dog::bark and $dogwood.Tree::bark, I'm distinguishing between two wholly unrelated actions (that they happen to have some of the same letters in their names is completely coincidental). So I have to know *what* a Dogwood object does; but I still don't have to know how it does it.

Or to look at it the other way around: Since we refer to things by name, those names have to be unique everywhere; so let's start out with long, "fully-qualified" names everywhere: $dog.Dog::bark(), $tree.Tree::bark(), $i.Int::succ, etc. Now everything's fine -- except that our fingers are getting tired from all that typing. We want to use shortcuts to say things like $dog.bark, because there's only one place that $dog can legitimately find a bark() method, and that's in the Dog class, so both we and Perl can easily figure out what is meant.

On the other hand, $dogwood.Dog::bark cannot be simplified by leaving out the "Dog::" because then it would be ambiguous. But if we look at it as starting with full names everywhere, and seeing what we can leave out (rather that starting with short names and having to add stuff in), I think it's not surprising.


In other cases, there may be no way to implicitly disambiguate. In those cases, there would need to be an explicit way to decide which hat the object is wearing.

I really don't think that deferring the decision works. The "freezing" technique described in the paper allows the consumer, C, to statically bind the method foo() in the methods in the appropriate role which call it.

The problem with "freezing" some methods into private ones is that those methods weren't meant to be private; if my role provides a .bark method, I need to be able to call it.

Dynamic binding defers the decision which causes implementation details to leak to consumers of C. This means that if you change your roles, your consumers will potentially need to be rewritten.

But if you merely change the implementation of how bark() works (either one), nothing needs to be rewritten. If you want to change from Tree::bark-ing to Dog::bark-ing, then you *should* be rewriting code, because you're completely changing what is going on, no less than if you changed from bark()ing to fetch()ing.


-David

Reply via email to