如何将参数部分绑定/应用到 R 中的函数?
这就是我走了多远,然后我意识到这种方法行不通......
bind <- function(fun,...)
{
argNames <- names(formals(fun))
bindedArgs <- list(...)
bindedNames <- names(bindedArgs)
function(argNames[!argNames %in% bindedArgs])
{
#TODO
}
}
谢谢!
这是 Curry 的一个版本,它既保留了对函数参数的惰性求值,又构造了一个打印效果适中的函数:
Curry <- function(FUN, ...) {
args <- match.call(expand.dots = FALSE)$...
args$... <- as.name("...")
env <- new.env(parent = parent.frame())
if (is.name(FUN)) {
fname <- FUN
} else if (is.character(FUN)) {
fname <- as.name(FUN)
} else if (is.function(FUN)){
fname <- as.name("FUN")
env$FUN <- FUN
} else {
stop("FUN not function or name of function")
}
curry_call <- as.call(c(list(fname), args))
f <- eval(call("function", as.pairlist(alist(... = )), curry_call))
environment(f) <- env
f
}
它基本上通过生成一个匿名函数来工作,就像你自己构建部分绑定一样。
实际上,这似乎可以解决
bind <- function(fun,...)
{
boundArgs <- list(...)
formals(fun)[names(boundArgs)] <- boundArgs
fun
}
但是,理想情况下,我希望绑定的参数从新函数中完全消失,以便可以使用名称规范调用新函数,例如add <- function(a,b) a+b我想(bind(add,a=2))(1)返回 3。
您是否尝试过查看 roxygen 的 Curry 功能?
> library(roxygen)
> Curry
function (FUN, ...)
{
.orig = list(...)
function(...) do.call(FUN, c(.orig, list(...)))
}
<environment: namespace:roxygen>
示例用法:
> aplusb <- function(a,b) {
+ a + 2*b
+ }
> oneplusb <- Curry(aplusb,1)
> oneplusb(2)
[1] 5
编辑:
Curry 被简洁地定义为接受命名或未命名的参数,但fun通过formal()赋值对参数的部分应用需要更复杂的匹配来模拟相同的功能。例如:
> bind <- function(fun,...)
+ {
+ argNames <- names(formals(fun))
+ boundArgs <- list(...)
+ boundNames <- names(boundArgs)
+ if(is.null(boundNames)) {
+ formals(fun)[1:length(boundArgs)] <- boundArgs
+ } else {
+ formals(fun)[match(names(boundArgs),argNames)] <- boundArgs
+ }
+ fun
+ }
> oneplusb <- bind(aplusb,1)
> oneplusb(2)
Error in 2 * b : 'b' is missing
因为此函数中的第一个参数仍然是a,所以您需要指定哪个参数2用于 ( b=),或者将其作为第二个参数传递。
> oneplusb
function (a = 1, b)
{
a + 2 * b
}
> oneplusb(b=2) ## or oneplusb(,2)
[1] 5