Skip to content

Instantly share code, notes, and snippets.

@hadley
Created August 14, 2013 14:26
Show Gist options
  • Save hadley/6231558 to your computer and use it in GitHub Desktop.
Save hadley/6231558 to your computer and use it in GitHub Desktop.
Some S3 brainteasers
  • UseMethod() has a special way of calling methods which has some weird consequences. Predict what the following code will return, then run it and read the help for UseMethod() to figure out what's going on. Write down the rules in the simplest form possible.

    y <- 1
    g <- function(x) { 
      y <- 2
      UseMethod("g")
    }
    g.numeric <- function(x) y
    g(10)
    
    h <- function(x) {
      x <- 10
      UseMethod("h")
    }
    h.character <- function(x) paste("char", x)
    h.numeric <- function(x) paste("num", x)
    
    h("a")
  • Internal generics don't dispatch on the implicit class of base types. Carefully read ?"internal generic" to determine why the length of f and g is different in the example below. What function helps distinguish between the behaviour of f and g?

    f <- function() 1
    g <- function() 2
    class(g) <- "function"
    class(f)
    class(g)
    
    length.function <- function(x) "function"
    
    length(f)
    length(g)
@akbertram
Copy link

For extra fun, some internal generics define their dispatch rules quite arbitrarily. cbind() and row() for example, are unique in supporting multiple dispatch, while (nearly) all other methods dispatch on only the first argument:

x <- structure(1:10, class="foo")
cbind.foo <- function(...) "FOO!"
cbind(1:10, x) 
cbind(data.frame(a=1:10), x)
cbind(matrix(1:10, nrow=10), x)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment