Here's how I think about it:
- Hierarchies have nothing to do with multimethods/GFs per se.
Here are the areas I'm looking to improve:
- There's no easy way to talk about "the method you would get if you
were dispatch value X". Note that this is not the same as call-next-
method, which reintroduces global ordering requirements, but allows
for easy explicit reuse of already-defined methods.
- Currently, a preference doesn't encompass the path through the
preferred value to its ancestors, but could.
- If you have a set of common preferences, there's no easy way to
create them in advance and share them among methods. There are issues
here related to ensuring preference consistency and caching.
Can we please move forward in trying to implement something better
than CLOS GFs? I have no interest in going backwards.
Rich
> Here are some problems/limitations of existing OO/GF systems that I
> don't intend to repeat:
...
I agree that these are not desirable features. I have had to work
around some of them many times in the past. Traditional OO combines
aspects that should better be handled separately.
> Here are the areas I'm looking to improve:
>
> - There's no easy way to talk about "the method you would get if you
> were dispatch value X". Note that this is not the same as call-next-
> method, which reintroduces global ordering requirements, but allows
> for easy explicit reuse of already-defined methods.
That would be VERY nice to have. More than once I ended up writing a
private function that I then called from several methods in the same
multimethod, to avoid code duplication.
> - Currently, a preference doesn't encompass the path through the
> preferred value to its ancestors, but could.
>
> - If you have a set of common preferences, there's no easy way to
> create them in advance and share them among methods. There are issues
> here related to ensuring preference consistency and caching.
At the moment, a multimethod takes two dispatch-oriented parameters:
a hierarchy and a dispatch function that returns a single item from
the hierarchy.
How about generalizing the dispatch function in two ways:
- it can return a sequence of items that will be tried in order
- it can access the hierarchy
Accessing the hierarchy is a minor point since this is already
possible (write a dispatch function that uses parents, ancestors,
etc.; for a hierarchy other than the global one, make the dispatch
function a closure that refers to the hierarchy). Maybe it could be
made more convenient.
Returning a sequence should be sufficient to let the dispatch
function handle any kind of preference. prefer-method could thus go
away. Instead, there would be a set of utility functions to
facilitate writing dispatch functions for common cases. A single
dispatch function could be used for any number of multimethods.
I think this should be sufficient to cover all cases you mentioned,
but of course it needs to be tried in practice.
Konrad.
I think your idea of specifying a sequence of items to try in the
dispatching function, at the point of definition for the multimethod,
violates the principle of allowing library consumers to easily extend
this on their own without having to contact the library designer.
Maybe I wasn't clear about one point: the return sequence is not the
sequence of concrete implementations to try (the dispatch function
wouldn't even necessarily know them), but a sequence of starting
points in the hierarchy from which the standard lookup would start.
Konrad.
One night's sleep later, I see that this is not sufficient. The
dispatch function is defined before the multimethod, and thus
potentially inside some library, which cannot know all the needs of
its potential clients. So yes, there has to be a way to specify
preferences later on.
One possibility would be to make the dispatch function itself a
multimethod, or have it call one, but I am not sure that's a good
solution.
Konrad.
> I've added get-method (SVN 1338).
Great, thanks!
> Note how you can name methods for diagnostic purposes. This doesn't
> introduce names into the namespace, just puts a name on the fn object.
It's also useful for recursive calls, if you are sure you want to
stay inside the method and not do a new dispatch.
Konrad.