Hi,
> ... Wrong. It looks like internally a[[1]] is always used instead of
a[[i]].
> The real problem it seems is that 'a' is treated as if it was of
> ength 1:
>
> > mapply(function(x, y) {x * y}, a, 1:3)
> [1] 101 202 303
> > mapply(function(x, y) {x * y}, a, 5)
> [1] 505
>
> In other words, internal dispatch works for [[ but not for length().
Documentation of mapply says > Arguments are recycled if necessary.
So, the function seems to work as documented.
One may be tempted to expect that what 'length()' says should take
precedence but
the '...' arguments in 'mapply' are documented
as> ...: arguments to vectorize over (vectors or lists of strictly
> positive length, or all of zero length).
So, the defining feature is that the arguments are vectors.
Since class A is not defined as a vector class, object 'a' is a scalar
(vector of length 1 in R) and therefore recycled.
It is probably not a good idea to redefine length() for class A without making
it a subclass of 'vector' (or something equivalent) since doing so
redefines a fundamental basic feature behind R's back.
Best regards,
Georgi
--
Dr Georgi Boshnakov tel: (+44) (0)161 306 3684
School of Mathematics fax: (+44) (0)161 306 3669
Alan Turing Building 1.125
The University of Manchester email: Georgi.Boshnakov at manchester.ac.uk
Oxford Road
Manchester M13 9PL
UK
Message: 7
Date: Wed, 14 Nov 2012 21:42:07 -0800
From: Herv? Pag?s <hpages at fhcrc.org>
To: R-devel at r-project.org
Subject: [Rd] bug with mapply() on an S4 object
Message-ID: <50A480AF.1030901 at fhcrc.org>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Hi,
Starting with ordinary vectors, so we know what to expect:
> mapply(function(x, y) {x * y}, 101:106, rep(1:3, 2))
[1] 101 204 309 104 210 318
> mapply(function(x, y) {x * y}, 101:106, 1:3)
[1] 101 204 309 104 210 318
Now with an S4 object:
setClass("A", representation(aa="integer"))
a <- new("A", aa=101:106)
> length(a)
[1] 1
Implementing length():
setMethod("length", "A", function(x) length(x at aa))
Testing length():
> length(a) # sanity check
[1] 6
No [[ yet for those objects so the following error is expected:
> mapply(function(x, y) {x * y}, a, rep(1:3, 2))
Error in dots[[1L]][[1L]] : this S4 class is not subsettable
Implementing [[:
setMethod("[[", "A", function(x, i, j, ...) x at aa[[i]])
Testing [[:
> a[[1]]
[1] 101
> a[[5]]
[1] 105
Trying mapply again:
> mapply(function(x, y) {x * y}, a, rep(1:3, 2))
[1] 101 202 303 101 202 303
Wrong. It looks like internally a[[1]] is always used instead of a[[i]].
The real problem it seems is that 'a' is treated as if it was of
length 1:
> mapply(function(x, y) {x * y}, a, 1:3)
[1] 101 202 303
> mapply(function(x, y) {x * y}, a, 5)
[1] 505
In other words, internal dispatch works for [[ but not for length().
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 fhcrc.org
Phone: (206) 667-5791
Fax: (206) 667-1319