[Rd] Dispatch mechanism seems to alter object before calling method on it
Hervé Pagès
hp@ge@ @ending from fredhutch@org
Wed May 16 17:33:44 CEST 2018
On 05/15/2018 09:13 PM, Michael Lawrence wrote:
> My understanding is that array (or any other structure) does not
> "simply" inherit from vector, because structures are not vectors in
> the strictest sense. Basically, once a vector gains attributes, it is
> a structure, not a vector. The methods package accommodates this by
> defining an "is" relationship between "structure" and "vector" via an
> "explicit coerce", such that any "structure" passed to a "vector"
> method is first passed to as.vector(), which strips attributes. This
> is very much by design.
It seems that the problem is really with matrices and arrays, not
with "structures" in general:
f <- factor(c("z", "x", "z"), levels=letters)
m <- matrix(1:12, ncol=3)
df <- data.frame(f=f)
x <- structure(1:3, titi="A")
Only the matrix looses its attributes when passed to a "vector"
method:
setGeneric("foo", function(x) standardGeneric("foo"))
setMethod("foo", "vector", identity)
foo(f) # attributes are preserved
# [1] z x z
# Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z
foo(m) # attributes are stripped
# [1] 1 2 3 4 5 6 7 8 9 10 11 12
foo(df) # attributes are preserved
# f
# 1 z
# 2 x
# 3 z
foo(x) # attributes are preserved
# [1] 1 2 3
# attr(,"titi")
# [1] "A"
Also if structures are passed to as.vector() before being passed to
a "vector" method, shouldn't as.vector() and foo() be equivalent on
them? For 'f' and 'x' they're not:
as.vector(f)
# [1] "z" "x" "z"
as.vector(x)
# [1] 1 2 3
Finally note that for factors and data frames the "vector" method gets
selected despite the fact that is( , "vector") is FALSE:
is(f, "vector")
# [1] FALSE
is(m, "vector")
# [1] TRUE
is(df, "vector")
# [1] FALSE
is(x, "vector")
# [1] TRUE
Couldn't we recognize these problems as real, even if they are by
design? Hopefully we can all agree that:
- the dispatch mechanism should only dispatch, not alter objects;
- is() and selectMethod() should not contradict each other.
Thanks,
H.
>
> Michael
>
>
> On Tue, May 15, 2018 at 5:25 PM, Hervé Pagès <hpages at fredhutch.org> wrote:
>> Hi,
>>
>> This was quite unexpected:
>>
>> setGeneric("foo", function(x) standardGeneric("foo"))
>>
>> setMethod("foo", "vector", identity)
>>
>> foo(matrix(1:12, ncol=3))
>> # [1] 1 2 3 4 5 6 7 8 9 10 11 12
>>
>> foo(array(1:24, 4:2))
>> # [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
>> 24
>>
>> If I define a method for array objects, things work as expected though:
>>
>> setMethod("foo", "array", identity)
>>
>> foo(matrix(1:12, ncol=3))
>> # [,1] [,2] [,3]
>> # [1,] 1 5 9
>> # [2,] 2 6 10
>> # [3,] 3 7 11
>> # [4,] 4 8 12
>>
>> So, luckily, I have a workaround.
>>
>> But shouldn't the dispatch mechanism stay away from the business of
>> altering objects before passed to it?
>>
>> Thanks,
>> H.
>>
>> --
>> 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 fredhutch.org
>> Phone: (206) 667-5791
>> Fax: (206) 667-1319
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__stat.ethz.ch_mailman_listinfo_r-2Ddevel&d=DwIFaQ&c=eRAMFD45gAfqt84VtBcfhQ&r=BK7q3XeAvimeWdGbWY_wJYbW0WYiZvSXAJJKaaPhzWA&m=gynT4YhbmVKZhnX4srXlCWZZRyVBMXG211CKgftdEs0&s=_I0aFHQVnXdBfB5kTLg9TxK_2LHdSuaB6gqZwSx1orQ&e=
>>
--
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 fredhutch.org
Phone: (206) 667-5791
Fax: (206) 667-1319
More information about the R-devel
mailing list