Использование sd как универсальной функции в R - PullRequest
8 голосов
/ 18 января 2011

Если у меня есть класс с именем foo, перегрузить функцию summary

summary.foo = function(x, ...) print("bar")

просто. Однако этот метод не работает с функцией sd, то есть1007 *

> bar = createFooClass()
> sd.foo = function(x, ...) print("Hi")
> sd(bar)
  error: is.atomic(x) is not TRUE

Как правильно перегрузить эту функцию?

Ответы [ 3 ]

7 голосов
/ 19 января 2011

Вы можете захватить любую неуниверсальную функцию, сделать ее (S3) общей и установить исходную версию в качестве версии по умолчанию. Например:

## make an S3 generic for sd
sd <- function(x, ...) UseMethod("sd")
## take the usual definition of sd,
## and set it to be the default method
sd.default <- stats::sd
## create a method for our class "foo"
sd.foo = function(x, ...) print("Hi")

Последним шагом, если он находится в пакете, является добавление аргумента ... к sd.default, чтобы разрешить прохождение проверок пакетов:

formals(sd.default) <- c(formals(sd.default), alist(... = ))

дает:

> args(sd.default)
function (x, na.rm = FALSE, ...) 
NULL
> args(stats::sd)
function (x, na.rm = FALSE) 
NULL

Это тогда дает желаемое поведение:

> bar <- 1:10
> sd(bar)
[1] 3.027650
> class(bar) <- "foo"
> sd(bar)
[1] "Hi"

Это задокументировано в разделе 7.1 руководства по написанию расширений

3 голосов
/ 19 января 2011

Вам необходимо определить новый шаблон для sd.

Самый простой способ - использовать S4, поскольку он автоматически обрабатывает метод sd по умолчанию:

setClass("foo", list(a = "numeric", names = "character"))

setGeneric("sd")

setMethod("sd", "foo", 
          function(x,  na.rm = FALSE){
              print("This is a foo object!")
              callNextMethod(x@a)
              })

tf <- new("foo", a = 1:10)
sd(tf)
#[1] "This is a foo object!"
#[1] 3.027650
1 голос
/ 18 января 2011

Посмотрите на код sd() --- он эффективно отправляет изнутри. Другими словами, это не универсальная функция, а обычная старая функция.

Самым простым может быть изменение sd() для перехода на класс foo.

...