Re: [R] Understanding S4 method dispatch

2013-08-14 Thread Hervé Pagès

And it doesn't even select "the first method lexicographically in the
ordering" (whatever that means):

  setClass("B", "NULL")
  setClass("A", "NULL")
  setMethod("show", "B", function(object) cat("B object\n"))
  setMethod("show", "A", function(object) cat("A object\n"))

  setClass("AB", contains=c("B", "A"))
  ab <- new("AB")

Then:

  > ab
  B object

  > is(ab)
  [1] "AB"   "B""A"".NULL" 


  [5] "NULL" "OptionalFunction" "optionalMethod"

So the order of the superclasses passed to 'contains' seems to
actually matter (even though I don't remember I've seen this
documented anywhere). Is it correct to speculate that, if the
distance is the same, and if the tie cannot be broken by looking
at whether one class involved in the tie extends the other one,
then the order in which the superclasses were passed to 'contains'
is looked at?

Last but not least, if you try to redefine class AB by switching
A and B in 'contains' again, it seems to have no effect:

  > setClass("AB", contains=c("A", "B"))
  > ab
  B object

except that now this contradicts is():

  > is(ab)
  [1] "AB"   "A""B"".NULL" 


  [5] "NULL" "OptionalFunction" "optionalMethod"

I'm just going to stop trying to sort this mess out :-/

H.

On 08/14/2013 09:54 AM, Hadley Wickham wrote:

On Wed, Aug 14, 2013 at 11:36 AM, Simon Zehnder  wrote:

Because the signature is always (A,A) or (B,B). Then, as in AB we have A and B 
and no relationship between A and B, R chooses the method lexicographically. 
The result is as expected: f for A is chosen.


It's not as expected, because it doesn't give a message. From ?Methods:

If there is no best match, the selection is ambiguous and a message is
printed noting which method was selected (the first method
lexicographically in the ordering) and what other methods could have
been selected.

Hadley



--
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: hpa...@fhcrc.org
Phone:  (206) 667-5791
Fax:(206) 667-1319

__
R-help@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.


Re: [R] Understanding S4 method dispatch

2013-08-14 Thread Hervé Pagès

Hi Zehnder,

You're right that the fact that B already inherits from A is probably
part of the story but it's not all the story:

  setClass("A", "NULL")
  setClass("B", "A")
  setMethod("show", "A", function(object) cat("A object\n"))
  setMethod("show", "B", function(object) cat("B object\n"))

  setClass("C", "B")
  setClass("AC", contains = c("A", "C"))
  ac <- new("AC")

Then:

  > ac
  A object

So even if B already inherits from A, A seems to be considered "closer"
to AC than B is. This is confirmed by showClass():

  > showClass("AC")
  Class "AC" [in ".GlobalEnv"]

  Slots:

  Name:  .xData
  Class:   NULL

  Extends:
  Class "C", directly
  Class "A", directly
  Class "B", by class "C", distance 2
  Class ".NULL", by class "A", distance 2
  Class "NULL", by class "A", distance 3, with explicit coerce
  Class "OptionalFunction", by class "A", distance 4, with explicit coerce
  Class "optionalMethod", by class "A", distance 4, with explicit coerce

and also reflected by is():

  > is(ac)
  [1] "AC"   "C""A""B" 

  [5] ".NULL""NULL" "OptionalFunction" 
"optionalMethod"


There seems to be an attempt at ordering the superclasses of a given
class (performed when the class is defined): first by distance, then,
by looking at whether one class involved in the tie inherits from the
other. Like in Hadley's example:

  setClass("AB", contains = c("A", "B"))
  ab <- new("AB")

Then:

  > ab
  B object

showClass("AB") reports that distance(AB, A) = distance(AB, B) so
there is a tie. However, this tie can be disambiguated because
B inherits from A. This disambiguation is reflected by the output
of is():

  > is(ab)
  [1] "AB"   "B""A"".NULL" 


  [5] "NULL" "OptionalFunction" "optionalMethod"

Unfortunately ?Methods is not particularly clear about all this.
You need to read it between the lines.

Note that ordering of superclasses is well defined in terms of distance
only (with no ties ever) if you don't use multiple inheritance. So this
is one more reason to stay away from multiple inheritance (just in case
you were still not convinced ;-) )

Cheers,
H.


On 08/14/2013 03:51 AM, Simon Zehnder wrote:

Ambiguity is indeed detected by R and the user is informed on it. But in the 
case of Hadley's example, I still believe, that the specific multiple 
inheritance structure creates this behavior. If you call:

showMethods("f")
Function: f (package .GlobalEnv)
x="A", y="A"
x="AB", y="AB"
 (inherited from: x="B", y="B")
x="B", y="B"

you see, that AB inherited the method from B. As B inherits already from A and 
AB does as well, AB would have two A objects, the one from its inheritance from 
A and the one from B. In the case of direct inheritance, the only slot is the 
.xData slot, which is NULL. If one class contains another one, it contains all 
its slots. As the .xData slot is the same for each class A, B and AB, R must 
remove the ambiguity of slots, this is done by allowing only one slot .xData, 
which is the one from B. So in some way A is hidden by B in AB - but this is 
actually a common technique in OOP. In C++ for example we have the same problem 
and we can define which members should be inherited if multiple inheritance is 
aware, by using the keyword 'virtual'.

Towards Hervé's second point:

If we build a class C:

setClass("C", contains = c("A"))
setMethod("f", signature("C", "C"), function(x, y) "C-C")

And then construct a multiple inheritance structure within a class BC:

setClass("BC", contains = c("B", "C"))
bc <- new("BC")

we see, that indeed the first lexicographical signature is chosen:

showMethods("f")
Function: f (package .GlobalEnv)
x="A", y="A"
x="B", y="B"
x="BC", y="BC"
 (inherited from: x="B", y="B")
x="C", y="C"

f(bc, bc)
[1] "B-B"

In this case, we have a 'true' tie in the inheritance structure: B from A and C 
from A, any one of the two As have to be taken into the BC object and the one 
from B is chosen. But method dispatch is in this case independent of the second 
level inheritance. B and C are not related directly to each other, so method 
dispatch is chosen lexicographically.

In my opinion the reason for the behavior lies in the specific multiple 
inheritance structure between AB, B and A.

Best

Simon




On Aug 14, 2013, at 2:11 AM, Hervé Pagès  wrote:


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 

Re: [R] Understanding S4 method dispatch

2013-08-14 Thread Hadley Wickham
On Wed, Aug 14, 2013 at 11:36 AM, Simon Zehnder  wrote:
> Because the signature is always (A,A) or (B,B). Then, as in AB we have A and 
> B and no relationship between A and B, R chooses the method 
> lexicographically. The result is as expected: f for A is chosen.

It's not as expected, because it doesn't give a message. From ?Methods:

If there is no best match, the selection is ambiguous and a message is
printed noting which method was selected (the first method
lexicographically in the ordering) and what other methods could have
been selected.

Hadley

-- 
Chief Scientist, RStudio
http://had.co.nz/

__
R-help@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.


Re: [R] Understanding S4 method dispatch

2013-08-14 Thread Simon Zehnder
Because the signature is always (A,A) or (B,B). Then, as in AB we have A and B 
and no relationship between A and B, R chooses the method lexicographically. 
The result is as expected: f for A is chosen. 

If you would do something like: 

setClass("A", contains = "list")
setClass("B", contains = "list")
setClass("AB", contains = c("A", "B"))

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")
setMethod("f", signature("B", "B"), function(x, y) "B-B")

ab <- new("AB")
f(ab, ab)

You get an ambiguity, as there is no function with signature pair that can be 
directly matched for A. But for B such a signature pair exists. So R chooses B. 
If you would specify again a function for signature (A,A) we are back:

setMethod("f", signature("A", "A"), function(x, y) "A-A")
f(ab, ab)


Best 

Simon


On Aug 14, 2013, at 5:25 PM, Hadley Wickham  wrote:

>> In my opinion the reason for the behavior lies in the specific multiple 
>> inheritance structure between AB, B and A.
> 
> So what if we don't make such a weird inheritance structure, and
> instead have A and B inherit from a common parent:
> 
> setClass("A", contains = "list")
> setClass("B", contains = "list")
> setClass("AB", contains = c("A", "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")
> 
> ab <- new("AB")
> f(ab, ab)
> 
> Why isn't there a warning about ambiguous dispatch?
> 
> Hadley
> 
> -- 
> Chief Scientist, RStudio
> http://had.co.nz/

__
R-help@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.


Re: [R] Understanding S4 method dispatch

2013-08-14 Thread Hadley Wickham
> In my opinion the reason for the behavior lies in the specific multiple 
> inheritance structure between AB, B and A.

So what if we don't make such a weird inheritance structure, and
instead have A and B inherit from a common parent:

setClass("A", contains = "list")
setClass("B", contains = "list")
setClass("AB", contains = c("A", "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")

ab <- new("AB")
f(ab, ab)

Why isn't there a warning about ambiguous dispatch?

Hadley

-- 
Chief Scientist, RStudio
http://had.co.nz/

__
R-help@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.


Re: [R] Understanding S4 method dispatch

2013-08-14 Thread Simon Zehnder
Ambiguity is indeed detected by R and the user is informed on it. But in the 
case of Hadley's example, I still believe, that the specific multiple 
inheritance structure creates this behavior. If you call:

showMethods("f")
Function: f (package .GlobalEnv)
x="A", y="A"
x="AB", y="AB"
(inherited from: x="B", y="B")
x="B", y="B"

you see, that AB inherited the method from B. As B inherits already from A and 
AB does as well, AB would have two A objects, the one from its inheritance from 
A and the one from B. In the case of direct inheritance, the only slot is the 
.xData slot, which is NULL. If one class contains another one, it contains all 
its slots. As the .xData slot is the same for each class A, B and AB, R must 
remove the ambiguity of slots, this is done by allowing only one slot .xData, 
which is the one from B. So in some way A is hidden by B in AB - but this is 
actually a common technique in OOP. In C++ for example we have the same problem 
and we can define which members should be inherited if multiple inheritance is 
aware, by using the keyword 'virtual'.

Towards Hervé's second point: 

If we build a class C:

setClass("C", contains = c("A"))
setMethod("f", signature("C", "C"), function(x, y) "C-C")

And then construct a multiple inheritance structure within a class BC:

setClass("BC", contains = c("B", "C"))
bc <- new("BC")

we see, that indeed the first lexicographical signature is chosen: 

showMethods("f")
Function: f (package .GlobalEnv)
x="A", y="A"
x="B", y="B"
x="BC", y="BC"
(inherited from: x="B", y="B")
x="C", y="C"

f(bc, bc)
[1] "B-B"

In this case, we have a 'true' tie in the inheritance structure: B from A and C 
from A, any one of the two As have to be taken into the BC object and the one 
from B is chosen. But method dispatch is in this case independent of the second 
level inheritance. B and C are not related directly to each other, so method 
dispatch is chosen lexicographically.

In my opinion the reason for the behavior lies in the specific multiple 
inheritance structure between AB, B and A. 

Best

Simon




On Aug 14, 2013, at 2:11 AM, Hervé Pagès  wrote:

> 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: hpa...@fhcrc.org
> Phone:  (206) 667-5791
> Fax:(206) 667-1319
> 
> __
> R-help@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.

__
R-help@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.


Re: [R] Understanding S4 method dispatch

2013-08-13 Thread Hervé Pagès

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: hpa...@fhcrc.org
Phone:  (206) 667-5791
Fax:(206) 667-1319

__
R-help@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.


Re: [R] Understanding S4 method dispatch

2013-08-13 Thread Simon Zehnder
If you take an example which works with slots,

setClass("A", representation(a = "numeric")
setClass("B", contains = c("A"), representation(b = "numeric"))
a <- new("A", a = 2)
b <- new("B", a = 3, b = 2)

setClass("AB", contains = c("A", "B"))
new("AB", a = 2, b = 3)

You see, that there is only one @a slot, the one inherited from B, that B 
inherits from A. If this were not the case, which slot should be taken, if we 
would call @a? To avoid this kind of ambiguity, only one A class is inherited 
to AB: the one B already inherits from A. 

You could create a class, that contains another A object in a slot:

setClass("AandB", contains = c("B"), representation(A = "A"))
new("AandB", a = 2, b = 3, A = new("A", a = 3))

Now back to your example: as there is only one A object inside the B object 
which is contained by the AB object, method dispatch works the way as it 
should: It looks for a method f for an AB object. It does not find one. Then it 
looks for a method f for the contained B object (as this is the only one 
contained in AB) and it finds a method. Then it calls this method on the B part 
of the object AB and the result is "B-B"

Best

Simon



On Aug 13, 2013, at 4:24 PM, Hadley Wickham  wrote:

>> 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.
> 
> Are you sure? That behaviour doesn't agree with the description of
> method dispatch given in ?Methods, not with getClass("AB") which shows
> that AB inherits from both A and B. (I totally agree that this is a
> bad idea, and unlikely to be useful in real life, but I'm trying to
> understand the details of S4 dispatch)
> 
>> getClass("AB")
> Class "AB" [in ".GlobalEnv"]
> 
> Slots:
> 
> Name:  .xData
> Class:   NULL
> 
> Extends:
> Class "B", directly
> Class "A", directly
> Class ".NULL", by class "A", distance 2
> Class "NULL", by class "A", distance 3, with explicit coerce
> Class "OptionalFunction", by class "A", distance 4, with explicit coerce
> Class "optionalMethod", by class "A", distance 4, with explicit coerce
> 
> -- 
> Chief Scientist, RStudio
> http://had.co.nz/

__
R-help@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.


Re: [R] Understanding S4 method dispatch

2013-08-13 Thread Hadley Wickham
> 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.

Are you sure? That behaviour doesn't agree with the description of
method dispatch given in ?Methods, not with getClass("AB") which shows
that AB inherits from both A and B. (I totally agree that this is a
bad idea, and unlikely to be useful in real life, but I'm trying to
understand the details of S4 dispatch)

> getClass("AB")
Class "AB" [in ".GlobalEnv"]

Slots:

Name:  .xData
Class:   NULL

Extends:
Class "B", directly
Class "A", directly
Class ".NULL", by class "A", distance 2
Class "NULL", by class "A", distance 3, with explicit coerce
Class "OptionalFunction", by class "A", distance 4, with explicit coerce
Class "optionalMethod", by class "A", distance 4, with explicit coerce

-- 
Chief Scientist, RStudio
http://had.co.nz/

__
R-help@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.


Re: [R] Understanding S4 method dispatch

2013-08-13 Thread Simon Zehnder
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  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@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.

__
R-help@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.


[R] Understanding S4 method dispatch

2013-08-13 Thread Hadley Wickham
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@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.