TSa wrote:
Jonathan Lang wrote:
> Of course, you then run into a problem if the class _doesn't_ redefine
> method equal; if it doesn't, then what is GenPointMixin::equal
> calling?

This is the reason why there is a type bound on the class that should
result in a composition error when the equal method is missing.

But it isn't missing; it's being inherited from the role.

Shouldn't the 'divert' be a trait of the method instead of a key/value
pair on the class?

I thought about doing it that way; but then the class wouldn't know to
look for it when composing the role.

And what does your syntax mean? Looks like the key
is indicating the method and the value is the namespace where method
lookup starts.

That was the idea.

>  And you also run into a problem if you want the class to
> track the position in polar coordinates instead of rectilinear ones -
> it would still represent a point conceptually, but the implementation
> of method equal (at least) would need to be overridden.

Oh, yes. Doing the right thing is difficult. Changing representation
of the point while keeping the interface can only be done in the class.
OTOH, the interface would include the rectilinear accessor methods.
And these are called in the equal method.

...unless the equal method is rewritten so that it doesn't call them.
That said, you're right that the rectlinear access methods will still
be there - but they won't neccessarily work the same way.  In
particular, I can see .x being rewritten to return $.r * cos($.a) when
used to retrieve the value.  Internally, the representation would be
in polar notation; externally, rectilinear accessors could still be
used - though they wouldn't be as efficient as polar accessors.

In the case of the equal method the dispatch slot contains the role's
closure which calls into the class' closure. There is no dispatch to the
role because the role is flattened out in the composition process.

Conceptually, yes; you can think of it in that way.  In practice, this
is implemented by having the class dispatch to the role if none of the
class' signatures match the call.  Bear in mind, though, that _every_
call follows this route: even a method call that originates in a
role's method (such as an attribute accessor) will start the dispatch
process with the class, then move to the roles if the class doesn't
work, and then move up the class hierarchy if the roles don't work.

It is interesting to think of another PolarPoint role that also has
an equal method that would conflict with the GenPoint one. Then the
class has to disambiguate. Which in turn requires the class to provide
an equal method that overrides both role versions.

Agreed.

Note that I think the conflict detection of role methods prevents the
composition of the equal method through the superclass interface.

Just to make sure we're speaking the same language: by "superclass",
you're referring to classes brought in via "is"; right?  If so, you're
correct: the presence of a valid method in any of the roles that a
class composes is sufficient to prevent the dispatch process from ever
reaching any of the superclasses.

I admit that this warps
the meaning of the class' equal method from being an aspect in the
role's method to the definer of the method. This can be a source of
subtle bugs. That is the class composer can't distinguish an aspect
method from a disambiguation one unless we introduce e.g. an 'is
disambig' trait. And e.g. an 'is override' trait when the class designer
wishes to replace a role method even if there's no conflict.

...and you would then have to apply the 'override' trait to every
class method that is used instead of the role method.  Note that as
written, this is the default approach, and you only have to do
something exotic in the (comparatively) rare situation where you want
the class to complete the role's method instead of replacing it.

> What inspired that comment?

Sorry, I didn't want to intimidate you.

I wasn't intimidated; just curious.

--
Jonathan "Dataweaver" Lang

Reply via email to