R: how to find what S3 method will be called on an object?

▼魔方 西西 提交于 2019-12-20 01:08:07

问题


I know about methods(), which returns all methods for a given class. Suppose I have x and I want to know what method will be called when I call foo(x). Is there a oneliner or package that will do this?

The shortest I can think of is:

sapply(class(x), function(y) try(getS3method('foo', y), silent = TRUE))

and then to check the class of the results... but is there not a builtin for this?

Update

The full one liner would be:

fm <- function (x, method) { 
  cls <- c(class(x), 'default')
  results <- lapply(cls, function(y) try(getS3method(method, y), silent = TRUE))
  Find(function (x) class(x) != 'try-error', results)   
}

This will work with most things but be aware that it might fail with some complex objects. For example, according to ?S3Methods, calling foo on matrix(1:4, 2, 2) would try foo.matrix, then foo.numeric, then foo.default; whereas this code will just look for foo.matrix and foo.default.


回答1:


findMethod defined below is not a one-liner but its body has only 4 lines of code (and if we required that the generic be passed as a character string it could be reduced to 3 lines of code). It will return a character string representing the name of the method that would be dispatched by the input generic given that generic and its arguments. (Replace the last line of the body of findMethod with get(X(...)) if you want to return the method itself instead.) Internally it creates a generic X and an X method corresponding to each method of the input generic such that each X method returns the name of the method of the input generic that would be run. The X generic and its methods are all created within the findMethod function so they disappear when findMethod exits. To get the result we just run X with the input argument(s) as the final line of the findMethod function body.

findMethod <- function(generic, ...) {
  ch <- deparse(substitute(generic))
  f <- X <- function(x, ...) UseMethod("X")
  for(m in methods(ch)) assign(sub(ch, "X", m, fixed = TRUE), "body<-"(f, value = m))
  X(...)
}

Now test it. (Note that the one-liner in the question fails with an error in several of these tests but findMethod gives the expected result.)

findMethod(as.ts, iris)
## [1] "as.ts.default"

findMethod(print, iris)
## [1] "print.data.frame"

findMethod(print, Sys.time())
## [1] "print.POSIXct"

findMethod(print, 22)
## [1] "print.default"

# in this example it looks at 2nd component of class vector as no print.ordered exists
class(ordered(3))
## [1] "ordered" "factor" 
findMethod(print, ordered(3))
## [1] "print.factor"

findMethod(`[`, BOD, 1:2, "Time")
## [1] "[.data.frame"


来源:https://stackoverflow.com/questions/42738851/r-how-to-find-what-s3-method-will-be-called-on-an-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!