While my question is related to this recent one, I suspect its answer(s) will have to do with the detailed workings of R's S4 object system.
What I would expect:
(TLDR; -- All indications are that as(4L, "numeric") should dispatch to a function whose body uses as.numeric(4L) to convert it to a "numeric" vector.)
Whenever one uses as(object, Class) to convert an object to the desired Class, one is really triggering a behind-the-scenes call to coerce(). coerce(), in turn, has a bunch of methods that are dispatched to based on the signature of the function call -- here the class of its first and second arguments. To see a list of all available S4 coerce() methods, one can run showMethods("coerce").
Doing so shows that there is only one method for converting to class "numeric". It's the one with signature from="ANY", to="numeric":
showMethods("coerce")
# Function: coerce (package methods)
# from="ANY", to="array"
# ... snip ...
# from="ANY", to="numeric"
# ... snip ...
That method uses as.numeric() to perform its conversion:
getMethod("coerce", c("ANY", "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 "ANY" "numeric"
# defined "ANY" "numeric"
Given its signature, and the fact that it's the only coerce() method for conversion to class "numeric",
I would've expected that the function shown above is what would be dispatched to by a call to as(4L, "numeric").
That expectation is only reinforced by running the following two checks.
## (1) There isn't (apparently!) any specific method for "integer"-->"numeric"
## conversion
getMethod("coerce", c("integer", "numeric"))
# Error in getMethod("coerce", c("integer", "numeric")) :
# no method found for function 'coerce' and signature integer, numeric
## (2) This says that the "ANY"-->"numeric" method will be used for "integer"-->"numeric"
## conversion
selectMethod("coerce", signature=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"
What actually happens:
(TLDR; In fact, calling as(4L, "numeric") loads and dispatches to a method that does nothing at all.)
Despite what all indications mentioned above, as(4L, "numeric") does not dispatch to the coerce() method for calls with signature c("ANY", "numeric").
Here are a couple of ways to show that:
## (1) as.numeric() would do the job, but as(..., "numeric") does not
class(as(4L, "numeric"))
#[1] "integer"
class(as.numeric(4L))
# [1] "numeric"
## (2) Tracing shows that the "generic" method isn't called
trace("coerce", signature=c("ANY", "numeric"))
as(c(FALSE, TRUE), "numeric") ## <-- It's called for "logical" vectors
# Tracing asMethod(object) on entry
# [1] 0 1
as(c("1", "2"), "numeric") ## <-- and for "character" vectors
# Tracing asMethod(object) on entry
# [1] 1 2
as(c(1L, 2L), "numeric") ## <-- but not for "integer" vectors
# [1] 1 2
untrace("coerce")
What method, then, is used? Well, apparently the act of calling as(4L, "numeric")
adds a new S4 method to the list of methods for coerce(), and it's what is used.
(Compare the results of the following calls to what they produced before we had attempted our
first "integer" to "character" conversion.)
## At least one conversion needs to be attempted before the
## "integer"-->"numeric" method appears.
as(4L, "numeric")
## (1) Now the methods table shows a new "integer"-->"numeric" specific method
showMethods("coerce")
# Function: coerce (package methods)
# from="ANY", to="array"
# ... snip ...
# from="ANY", to="numeric"
# ... snip ...
# from="integer", to="numeric" ## <-- Here's the new method
# ... snip ...
## (2) selectMethod now tells a different story
selectMethod("coerce", signature=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"
My questions:
Why does
as(4L, "numeric")not dispatch to the availablecoerce()method forsignature=c("ANY", "numeric")?How/why does it instead add a new method to the S4 methods table?
From where (in R's source code or elsewhere) does the definition of the
coerce()method forsignature=c("integer", "numeric")come?