Каковы рекомендуемые практики для полиморфизма функций в R? - PullRequest
10 голосов
/ 28 октября 2011

Предположим, я хочу написать функцию в R, которая является функцией нескольких достаточных статистических данных для некоторых данных.Например, предположим, что функция, назовите ее foo.func, зависит только от среднего значения выборки данных.Для удобства я думаю, что пользователи могут захотеть передать foo.func выборку случайных величин (в этом случае foo.func вычисляет среднее значение выборки), или выборку означают сами, что все это foo.func потребности.Из соображений эффективности последнее предпочтительнее, если вызывается несколько функций, таких как foo.func, которые могут принимать среднее значение выборки.В этом случае среднее значение нужно вычислять только один раз (в реальной задаче, которую я имею в виду, рассматриваемая выборочная статистика может потребовать значительных вычислительных ресурсов).новичок (передать данные, позволить функции вычислить достаточную статистику), а также эксперт (предварительно вычислить достаточную статистику для эффективности и передать ее).Каковы рекомендуемые методы для этого?У меня есть логический флаг?Несколько аргументов?Некоторые способы сделать это могут быть:

#optional arguments
foo.func <- function(xdata, suff.stats=NULL) {
  if (is.null(suff.stats)) {
    suff.stats <- compute.suff.stats(x)
  }
  #now operate on suff.stats
}

или

#flag input
foo.func <- function(data.or.stat, gave.data=TRUE) {
  if (gave.data) {
    data.or.stat <- compute.suff.stats(data.or.stat)
  }
  #now operate on data.or.stat
}

Я склоняюсь к первому, я думаю

Ответы [ 2 ]

9 голосов
/ 28 октября 2011

R способ реализации полиморфизма - через модель CLOS (OO Common Lisp), где методы связаны с общими функциями (глаголами), а не с классами (существительными).Например,

# suprising that there is not an equivalent function in R
# to propagate inheritance...
addclass <- function(x,classname) structure(x,class=append(class(x),classname))

# this should be your main function that does stuff
# here, the identity function is assigned for example
dostuff <- identity

# define generic function and methods
foo <- function(x,...) UseMethod("foo")
foo.raw <- function(x,...) dostuff(mean(x))
foo.stats <- function(x,...) dostuff(x)

# define two types of inputs
x <- 1:10
x <- addclass(x,"raw")

y <- 5
y <- addclass(y,"stats")

# apply
foo(x)
# [1] 5.5
foo(y)
# [1] 5
# attr(,"class")
# [1] "numeric" "stats"  

В примере использовалась модель ОО S3 ООП, что, я думаю, вполне достаточно;S4 более современный и безопасный, но добавляет много шаблонного.

7 голосов
/ 28 октября 2011

Вы также можете встраивать функции в аргументы, например:

foo.func <- function(x, suff.stats = foo.func.suff.stat(x)){
  # your code here
}

Как пример:

foo.func <- function(x, avg = mean(x)){
  return(avg)
}

foo.func(1:20)
foo.func(avg = 42)

В качестве альтернативы вы можете использовать настройку по умолчанию NULL для различных аргументов и проверить на is.null(argument), или просто проверить значение missing(argument) для каждого аргумента, который вы можете вычислить.


Обновление 1: я ошибся, предложив использовать значение по умолчанию NA: гораздо более уместно использовать NULL. Использование NA и is.na() будет вести себя странно для векторных входных данных, тогда как NULL - это просто один объект - нельзя создать вектор со значениями NULL, поэтому is.null(argument) ведет себя как ожидалось. Извиняюсь за забывчивость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...