On Mar 24, 3:39 pm, Meikel Brandmeyer <m...@kotka.de> wrote:
> Hi,
>
> Am 24.03.2009 um 18:51 schrieb mikel:
>
> >>> (define-method add [x y] ...)
> >>> (define-method add [[x java.lang.Integer] y] ...)
> >>> (define-method add [x [y java.lang.Integer]] ...)
>
> >>> and call (add 3 3). Which of the methods is chosen?
>
> >> Isn't it the second, which is the most specific on the first
> >> argument ?
> >> (I think I remember this from CLOS ...)
>
> > That's correct.
>
> I'm still not sure I understand how this is resolved. Suppose
> the following situation:
>
> (define-method foo [x some.inter.Face] ...)
> (define-method foo [x some.other.Interface] ...)
>
> Now suppose you call this function foo with something like
> (proxy [some.inter.Face some.other.Interface] [] ...). Which
> magic decides which method to use?
Presently, that depends on what type you tell your proxy object to
have, or, alternatively, what matching sequence you tell your generic
function to have.
The default matching sequence presently relies on the Clojure function
named "type", which is not defined for all possible Clojure values.
You can, for example, use proxy to create an object for which type is
not defined. If you then apply a generic function to that value, and
the gf was created with the default dispatch sequence, the gf will
raise an exception, because type raises an exception. The solutions
open to you in the present implementation are: 1) give your proxy
object a type (in the sense of the Clojure type function); or (2)
create your generic function with a matching sequence suited to values
for which type is not defined.
A more comprehensive and automatic solution that is in the spirit of
CLOS would be to arrange for your example to dispatch to the
some.inter.Face method, because that's the one that appears farthest
to the left in your proxy expression. That wouldn't be particularly
hard to arrange; it would mean a special case for values for which
type is not defined, and a small adjustment to the code that measures
specificity of matches in the case of matching on class. A possible
monkey wrench is that this approach can only be made to work if we can
reliably infer from a proxy object the order of the class and
interfaces as they appeared in the proxy expression that created it; I
don't know off the top of my head whether we can safely make that
assumption.
CLOS says that if two matches are otherwise equally specific, the one
on the left wins. Similarly, it says that if two classes define slots
with the same name, the one farthest from the root of the class
heterarchy (as defined by a standard traversal algorithm) wins. You
can make a theoretical argument that these choices are arbitrary, and
that the programmer should control those decisions. In practice, the
CLOS approach is not a problem because:
(1) the standard choices are, in practice, the ones that least often
surprise programmers using them In other words, the assumption that
parameters on the left trump those on the right seems to suit most
people's intuitions; similarly, they seem to be comfortable with the
assumption that slots defined "later" trump those defined "earlier".
(2) if you *really* want the decisions to fall out a different way,
mechanisms are provided with which you can make that happen.
I'm a fan of CLOS in this respect: I think the default mechanism for
dispatch works well, and its arbitrariness is fine, because it's easy
to understand, it very rarely produces surprises, and in those rare
cases where it really isn't what you want, you have the power to
change it.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---