YA S4 method dispatch question

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

YA S4 method dispatch question

Paul Roebuck
I recently encountered this and was wondering if someone
could explain what happened. Basis of question involves
what the difference between the calls makes as the end
result is the same:

> identical(matrix(1:8, nrow = 1), array(1:8, c(1, 8)))
TRUE

If I run the code below as shown, I get the following:

> foo(1:8, 4)
foo (vector, numeric)
         val = 4
foo (matrix, ANY)
         val = 500
foo (matrix, numeric)
         val = 500
[1] 500 500 500 500 500 500 500 500

Exchanging the current return for one of the commented ones
(HERE) yields the expected answer:

> foo(1:8, 4)
foo (vector, numeric)
         val = 4
foo (matrix, numeric)
         val = 4
[1] 4 4 4 4 4 4 4 4


When invoked with array(), it loses track of the second
parameter and gives the wrong answer. While it would seem
to have something to do with the first parameter's
evaluation time, I don't follow why one works and the other
doesn't. Forcing the evaluation via assignment (third case)
also provides the correct result.

Example code follows:


##------------------------------------------------------------------------------
library(methods)

setGeneric("foo",
           function(x, val = 500) {
               standardGeneric("foo")
           })

setMethod("foo",
          signature(x = "vector", val = "numeric"),
          function(x, val) {
              cat(match.call()[[1]], "(vector, numeric)", "\n")
              cat("\t", "val =", val, "\n")
## HERE ##
#              return(drop(callGeneric(matrix(x, nrow = 1), val)))
              return(drop(callGeneric(array(x, c(1, length(x)), val))))
#              return(drop(callGeneric(xm <- array(x, c(1, length(x))), val)))
          })

setMethod("foo",
          signature(x = "vector"),
          function(x, val) {
              cat(match.call()[[1]], "(vector, ANY)", "\n")
              callGeneric(x, val)
          })

setMethod("foo",
          signature(x = "matrix", val = "numeric"),
          function(x, val) {
              cat(match.call()[[1]], "(matrix, numeric)", "\n")
              cat("\t", "val =", val, "\n")
              return(apply(x, c(1, 2), function(m, v) { m <- v }, val))
          })

setMethod("foo",
          signature(x = "matrix"),
          function(x, val) {
              cat(match.call()[[1]], "(matrix, ANY)", "\n")
              cat("\t", "val =", val, "\n")
              callGeneric(x, val)
          })

setMethod("foo",
          signature(x = "array"),
          function(x, val) {
              cat(match.call()[[1]], "(array, ANY)", "\n")
              stop(sprintf("method not defined for %s argument",
data.class(x)))
          })

setMethod("foo",
          signature(x = "ANY"),
          function(x, val) {
              cat(match.call()[[1]], "(ANY, ANY)", "\n")
              stop(sprintf("method not defined for %s argument",
data.class(x)))
          })

----------------------------------------------------------
SIGSIG -- signature too long (core dumped)

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: YA S4 method dispatch question

Martin Morgan
You won't like this ...;)

return(drop(callGeneric(array(x,
                              c(1, length(x)),
                              val)
                        )))

i.e., 'val' is inside 'array'!

I was discouraged from answering sooner by the complexity of your
example; simplifying it might have provided an immediate answer...

> x <- 1:8
> foo(array(x, c(1,length(x)), val)
+

! Martin




Paul Roebuck <[hidden email]> writes:

> I recently encountered this and was wondering if someone
> could explain what happened. Basis of question involves
> what the difference between the calls makes as the end
> result is the same:
>
>> identical(matrix(1:8, nrow = 1), array(1:8, c(1, 8)))
> TRUE
>
> If I run the code below as shown, I get the following:
>
>> foo(1:8, 4)
> foo (vector, numeric)
> val = 4
> foo (matrix, ANY)
> val = 500
> foo (matrix, numeric)
> val = 500
> [1] 500 500 500 500 500 500 500 500
>
> Exchanging the current return for one of the commented ones
> (HERE) yields the expected answer:
>
>> foo(1:8, 4)
> foo (vector, numeric)
> val = 4
> foo (matrix, numeric)
> val = 4
> [1] 4 4 4 4 4 4 4 4
>
>
> When invoked with array(), it loses track of the second
> parameter and gives the wrong answer. While it would seem
> to have something to do with the first parameter's
> evaluation time, I don't follow why one works and the other
> doesn't. Forcing the evaluation via assignment (third case)
> also provides the correct result.
>
> Example code follows:
>
>
> ##------------------------------------------------------------------------------
> library(methods)
>
> setGeneric("foo",
>            function(x, val = 500) {
>                standardGeneric("foo")
>            })
>
> setMethod("foo",
>           signature(x = "vector", val = "numeric"),
>           function(x, val) {
>               cat(match.call()[[1]], "(vector, numeric)", "\n")
>               cat("\t", "val =", val, "\n")
> ## HERE ##
> #              return(drop(callGeneric(matrix(x, nrow = 1), val)))
>               return(drop(callGeneric(array(x, c(1, length(x)), val))))
> #              return(drop(callGeneric(xm <- array(x, c(1, length(x))), val)))
>           })
>
> setMethod("foo",
>           signature(x = "vector"),
>           function(x, val) {
>               cat(match.call()[[1]], "(vector, ANY)", "\n")
>               callGeneric(x, val)
>           })
>
> setMethod("foo",
>           signature(x = "matrix", val = "numeric"),
>           function(x, val) {
>               cat(match.call()[[1]], "(matrix, numeric)", "\n")
>               cat("\t", "val =", val, "\n")
>               return(apply(x, c(1, 2), function(m, v) { m <- v }, val))
>           })
>
> setMethod("foo",
>           signature(x = "matrix"),
>           function(x, val) {
>               cat(match.call()[[1]], "(matrix, ANY)", "\n")
>               cat("\t", "val =", val, "\n")
>               callGeneric(x, val)
>           })
>
> setMethod("foo",
>           signature(x = "array"),
>           function(x, val) {
>               cat(match.call()[[1]], "(array, ANY)", "\n")
>               stop(sprintf("method not defined for %s argument",
> data.class(x)))
>           })
>
> setMethod("foo",
>           signature(x = "ANY"),
>           function(x, val) {
>               cat(match.call()[[1]], "(ANY, ANY)", "\n")
>               stop(sprintf("method not defined for %s argument",
> data.class(x)))
>           })
>
> ----------------------------------------------------------
> SIGSIG -- signature too long (core dumped)
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

array dimname argument (was Re: YA S4 method dispatch question)

Paul Roebuck
On Tue, 9 May 2006, Martin Morgan wrote:

> You won't like this ...;)
>
> return(drop(callGeneric(array(x,
>                               c(1, length(x)),
>                               val)
>                         )))
>
> i.e., 'val' is inside 'array'!
>
> I was discouraged from answering sooner by the complexity of your
> example; simplifying it might have provided an immediate answer...
>
> > x <- 1:8
> > foo(array(x, c(1,length(x)), val)
> +
>

Geez... I should have noticed that. Thanks for the catch.
I am rather surprised (never having tried it before) that
array() silently disregards my unintentional dimname
argument.

> x <- 1:8
> matrix(x, 1, length(x), dimnames = "argument used")
Error in matrix(x, 1, dimnames = "argument used") :
        'dimnames' must be a list
> array(x, c(1, length(x)), "argument silently ignored")
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    1    2    3    4    5    6    7    8
> array
function (data = NA, dim = length(data), dimnames = NULL)
{
    data <- as.vector(data)
    vl <- prod(dim)
    if (length(data) != vl) {
        if (vl > .Machine$integer.max)
            stop("'dim' specifies too large an array")
        data <- rep(data, length.out = vl)
    }
    if (length(dim))
        dim(data) <- dim
    if (is.list(dimnames) && length(dimnames)) ##HERE##
        dimnames(data) <- dimnames
    data
}
<environment: namespace:base>

The matrix method performs no check prior to assigning
dimnames. Why doesn't array function the same way?

----------------------------------------------------------
SIGSIG -- signature too long (core dumped)

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel