Hi all, Any insight into the code below would be appreciated - I don't understand why two methods which I think should have equal distance from the call don't. Thanks! Hadley # Create simple class hierarchy setClass("A", "NULL") setClass("B", "A") a <- new("A") b <- new("B") setGeneric("f", function(x, y) standardGeneric("f")) setMethod("f", signature("A", "A"), function(x, y) "A-A") setMethod("f", signature("B", "B"), function(x, y) "B-B") # These work as I expect f(a, a) f(b, b) setClass("AB", contains = c("A", "B")) ab <- new("AB") # Why does this return B-B? Shouldn't both methods be an equal distance? f(ab, ab) # These both return distance 1, as I expected extends("AB", "A", fullInfo=TRUE)@distance extends("AB", "B", fullInfo=TRUE)@distance # So why is signature("B", "B") closer than signature("A", "A") -- Chief Scientist, RStudio http://had.co.nz/
Hadley, The class AB inherits from A and from B, but B already inherits from class A. So actually you only have an object of class B in your object of class AB. When you call the function f R looks for a method f for AB objects. It does not find such a method and looks for a method of the object inherited from, B. Such a method is present and is then executed. The inheritance structure has to be changed. The behavior is actually desired, as if this behavior weren't given a diamond class inheritance would be fatal. Best Simon On Aug 13, 2013, at 3:08 PM, Hadley Wickham <h.wickham at gmail.com> wrote:> Hi all, > > Any insight into the code below would be appreciated - I don't > understand why two methods which I think should have equal distance > from the call don't. > > Thanks! > > Hadley > > # Create simple class hierarchy > setClass("A", "NULL") > setClass("B", "A") > > a <- new("A") > b <- new("B") > > setGeneric("f", function(x, y) standardGeneric("f")) > setMethod("f", signature("A", "A"), function(x, y) "A-A") > setMethod("f", signature("B", "B"), function(x, y) "B-B") > > # These work as I expect > f(a, a) > f(b, b) > > setClass("AB", contains = c("A", "B")) > ab <- new("AB") > > # Why does this return B-B? Shouldn't both methods be an equal distance? > f(ab, ab) > > # These both return distance 1, as I expected > extends("AB", "A", fullInfo=TRUE)@distance > extends("AB", "B", fullInfo=TRUE)@distance > # So why is signature("B", "B") closer than signature("A", "A") > > -- > Chief Scientist, RStudio > http://had.co.nz/ > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
Hi Hadley, I suspect that the dispatch algorithm doesn't realize that selection is ambiguous in your example. For 2 reasons: (1) When it does realize it, it notifies the user: setClass("A", "NULL") setGeneric("f", function(x, y) standardGeneric("f")) setMethod("f", signature("A", "ANY"), function(x, y) "A-ANY") setMethod("f", signature("ANY", "A"), function(x, y) "ANY-A") a <- new("A") Then: > f(a, a) Note: method with signature ?A#ANY? chosen for function ?f?, target signature ?A#A?. "ANY#A" would also be valid [1] "A-ANY" (2) When dispatch is ambiguous, the "first method lexicographically in the ordering" should be selected (according to ?Methods). So it should be A#A, not B#B. So it looks like a bug to me... Cheers, H. On 08/13/2013 06:08 AM, Hadley Wickham wrote:> Hi all, > > Any insight into the code below would be appreciated - I don't > understand why two methods which I think should have equal distance > from the call don't. > > Thanks! > > Hadley > > # Create simple class hierarchy > setClass("A", "NULL") > setClass("B", "A") > > a <- new("A") > b <- new("B") > > setGeneric("f", function(x, y) standardGeneric("f")) > setMethod("f", signature("A", "A"), function(x, y) "A-A") > setMethod("f", signature("B", "B"), function(x, y) "B-B") > > # These work as I expect > f(a, a) > f(b, b) > > setClass("AB", contains = c("A", "B")) > ab <- new("AB") > > # Why does this return B-B? Shouldn't both methods be an equal distance? > f(ab, ab) > > # These both return distance 1, as I expected > extends("AB", "A", fullInfo=TRUE)@distance > extends("AB", "B", fullInfo=TRUE)@distance > # So why is signature("B", "B") closer than signature("A", "A") >-- Herv? Pag?s Program in Computational Biology Division of Public Health Sciences Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N, M1-B514 P.O. Box 19024 Seattle, WA 98109-1024 E-mail: hpages at fhcrc.org Phone: (206) 667-5791 Fax: (206) 667-1319