我想在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方式是什么?任务很简单,所以我希望语法尽可能简单 - 没有抽象类或类似的。
答案 0 :(得分: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 :(得分: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
有一些更复杂的选项,使用表达式和符号,即计算语言。请告诉您是否对此类事情感兴趣,我们可以提供更多帮助。
答案 2 :(得分:1)
S3样式函数调度确实让人想起鸭子打字。您可以定义通用函数名称(以下示例中的“声音”),并覆盖每个类的不同函数。根据参数的class属性,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是古怪的,有时候只是没有一种漂亮的做事方式。