Hi John,
John Chambers wrote:
The example is confusing and debatable, but not an obvious bug. And
your presentation of it is the cause of much of the confusion
(unintentionally I'm sure).
First, slipping from the as() function to methods for the coerce()
function might surprise a less experienced user. And in fact, that is
the point here. If you look at the as() function, it jumps through
several hoops and in particular selects a method from coerce in such a
way as NOT to use inheritance on the from= argument. (I think this
makes sense in this case). So I would assert that your selectMethod()
output below came from a different session than the as(1:4, "numeric").
Starting from a clean session with R 2.10.1:
> class(as(1:4,"numeric"))
[1] "integer"
> selectMethod("coerce", c("integer","numeric"))
Method Definition:
function (from, to = "numeric", strict = TRUE)
if (strict) {
class(from) <- "numeric"
from
} else from
<environment: namespace:methods>
Signatures:
from to
target "integer" "numeric"
defined "integer" "numeric"
Note, no call to as.numeric(). In a session without a previous call to
as(), your selectMethod() call triggered a standard inherited method
selection. And if you had then gone on to as(), the result would have
been different.
Yes indeed. From a fresh start:
> invisible(selectMethod("coerce", c("integer","numeric")))
> class(as(1:4, "numeric"))
[1] "numeric"
But without the initial call to selectMethod(), as(1:4, "numeric")
returns an integer vector.
Sorry but it's hard for me to understand the reasons for having
such behaviour, especially when selectMethod() is described as a
function "to *look* for a method corresponding to a given generic
function and signature". Apparently it does more than just looking...
In a different clean session:
> getMethod("coerce", c("integer", "numeric"))
Error in getMethod("coerce", c("integer", "numeric")) :
No method found for function "coerce" and signature integer, numeric
> selectMethod("coerce", c("integer", "numeric"))
Method Definition:
function (from, to, strict = TRUE)
{
value <- as.numeric(from)
if (strict)
attributes(value) <- NULL
value
}
<environment: namespace:methods>
Signatures:
from to
target "integer" "numeric"
defined "ANY" "numeric"
> class(as(1:4,"numeric"))
[1] "numeric"
No argument about this being confusing. Perhaps one should prohibit
standard selectMethod() on coerce() but that seems a bit arcane to
thwart folks like you!
Suggested improvements for the current implementation are welcome, so
long as they consider the best definition of as() in the general sense.
So one problem seems to be that, on a fresh start, *both*
as(1:4, "numeric")
and
selectMethod("coerce", c("integer", "numeric"))
will cache a coerce method for the c("integer", "numeric") signature,
but they don't cache the *same* method!
The automatic method cached by 'as(1:4, "numeric")' seems to be
coming from:
getClassDef("integer")@contains$nume...@coerce
Maybe one way to improve things would be to modify this part of
the class definition for "integer" so it is in sync with
selectMethod("coerce", c("integer", "numeric")).
There are other situations where the coerce methods are not
in sync:
> getClassDef("factor")@contains$inte...@coerce
function (from, strict = TRUE)
{
attributes(from) <- NULL
from
}
<environment: namespace:methods>
> selectMethod("coerce", c("factor", "integer"))
Method Definition:
function (from, to, strict = TRUE)
{
value <- as.integer(from)
if (strict)
attributes(value) <- NULL
value
}
<environment: namespace:methods>
That isn't a problem here because both methods will produce
the same result but is there any reason why the former
couldn't use the same code as the latter?
A more radical approach would be to have a call to
selectMethod("coerce", c("integer", "numeric"))
have the same effect on the table of coerce methods than a
call to
as(1:4, "numeric")
i.e. the former will insert the same automatic method as the
latter. That means that all the hard work made by the as()
function in order to find/create/cache an appropriate method
would need to be moved to selectMethod() so in that function
'f="coerce"' would become a special case.
Then as() would become a 10 line function (or less) that would
basically delegate to selectMethod("coerce", ...) to do the hard
work. This solution seems better to me as it would then guarantee
consistency between what as() does and what
selectMethod("coerce", ...) says.
Cheers,
H.
Regards,
John
On 3/31/10 3:52 PM, Hervé Pagès wrote:
Hi,
> class(as(1:4, "numeric"))
[1] "integer"
Surprising but an explanation could be that an integer
vector being a particular case of numeric vector, this
coercion has nothing to do because 1:4 is already numeric.
And indeed:
> is.numeric(1:4)
[1] TRUE
> is.numeric(as(1:4, "numeric"))
[1] TRUE
However, 'as(1:4, "numeric")' is inconsistent with
> class(as.numeric(1:4))
[1] "numeric"
And, even more confusing, if you look at the coerce,ANY,numeric
method:
> selectMethod("coerce", c("integer", "numeric"))
Method Definition:
function (from, to, strict = TRUE)
{
value <- as.numeric(from)
if (strict)
attributes(value) <- NULL
value
}
<environment: namespace:methods>
Signatures:
from to
target "integer" "numeric"
defined "ANY" "numeric"
it calls as.numeric()!
So how can 'as(1:4, "numeric")' not return the same thing as
'as.numeric(1:4)' looks like a mystery to me. Could it be
conceivable that I found a bug?
Cheers,
H.
> sessionInfo()
R version 2.11.0 Under development (unstable) (2010-03-15 r51282)
x86_64-unknown-linux-gnu
locale:
[1] LC_CTYPE=en_CA.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_CA.UTF-8 LC_COLLATE=en_CA.UTF-8
[5] LC_MONETARY=C LC_MESSAGES=en_CA.UTF-8
[7] LC_PAPER=en_CA.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_CA.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
--
Hervé Pagès
Program in Computational Biology
Division of Public Health Sciences
Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N, M2-B876
P.O. Box 19024
Seattle, WA 98109-1024
E-mail: hpa...@fhcrc.org
Phone: (206) 667-5791
Fax: (206) 667-1319
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel