2013-03-25 3 views
0

Я хочу сделать очень простую вещь в R - иметь алгоритм, который я могу легко параметризовать с помощью набора функций. Я был уверен, что смогу сделать что-то вроде утиных объектов. Вот идея показано на очень простой код:R простые объекты с утиной с методами

par1.generate <- function(n) { 
    runif(n, min=0, max=1000) 
} 

par1.mean <- function(vec) { 
    mean(vec) 
} 


par2.generate <- function(n) { 
    round(runif(n, min=0, max=1000)) 
} 

par2.mean <- function(vec) { 
    mean(vec, trim=0.2) 
} 

#the "algorithm" 

alg <- function(par) { 
    v <- par.generate(10) 
    par.mean(v) 
} 

alg(par1) 
alg(par2) 

Если бы я попытался запустить этот код я хотел бы получить что-то вроде

Ошибка в ALG (PAR1): Не удалось найти функцию «par.mean»

Таким образом, я предполагаю, что мой интуитивный подход не работает.

Что такое способ R сделать что-то подобное? Задача проста, поэтому я предпочел бы, чтобы синтаксис был как можно более простым - никаких абстрактных классов или подобных.

+1

Могу предложить вам ознакомиться с классами «S3». Их очень, очень легко создать, но это требует * некоторых усилий. В частности, вам нужно создать функцию по умолчанию. –

ответ

2

Другой вариант - использовать список функций.

par1 <- list(generate=par1.generate,mean=par1.mean) 
par2 <- list(generate=par2.generate,mean=par2.mean) 

alg <- function(par) { 
    v <- par$generate(10) 
    par$mean(v) 
} 

alg(par1) 
[1] 495.2501 
alg(par2) 
[1] 481 
1

Использование match.fun и передать имена как строки:

alg <- function(par) { 
    v <- (match.fun(paste(par,"generate",sep=".")))(10) 
    (match.fun(paste(par,"mean",sep=".")))(v) 
} 

я получаю:

# > alg("par1") 
# [1] 615.5656 
# > alg("par2") 
# [1] 509 

Есть некоторые более сложные варианты, с помощью выражений и символов, то есть вычисления на языке. Скажите, если вы заинтересованы в таких вещах, и мы можем помочь больше.

+0

Мне не нравится это решение, так как его идея похожа на 'eval()' или '# define', но я вижу, что это то, что я мог бы использовать очень быстро. – nietaki

1

Отправка функции стиля S3 действительно несколько напоминает напоминание утки. Вы можете определить общее имя функции («звук» в примере ниже) и переопределить различные функции для каждого класса. В зависимости от атрибута класса аргумента R выбирает соответствующую функцию. В частности, ознакомьтесь с UseMethod, который является центром механизма отправки функций R.

Пример адаптирован из http://www.r-bloggers.com/the-s3-oop-system/:

# Set up dispatch for the generic function sound: 
sound <- function(x) UseMethod("sound", x) 

# Methods are defined with a naming convention: method.class: 
# This defines the method sound on class dog: 
sound.dog <- function(x) "bark" 
# Same for cow: 
sound.cow <- function(x) "moo" 
# Fallback: 
sound.default <- function(x) "animal sound" 

# The methods function can find out which classes a generic function was designed for: 
> methods("sound") 
[1] sound.cow  sound.default sound.dog 

# R looks for methods in the order in which they appear in the class vector until it found the appropriate method to operate on. 
# This makes multiple-inheritance possible 

> x <- structure("cat", class = c("cat", "dog", "cow")) 
> sound(x) 
[1] "bark" 

Но мне кажется, вы пытаетесь пожелать особенности языка, что R не имеет. R - изворотливый, и иногда просто не очень хорошо.