我想添加一些函数f1,f2,...,fn,这样我就有了一个新函数,它产生f(x)= f1(x)+ ... + fn(x)(称为逐点加法).所以我有一个功能列表并尝试过
Reduce("funadd",fun.list)
Run Code Online (Sandbox Code Playgroud)
funadd定义的地方
funadd <- function(f1,f2){
retfun <- function(x){
f1(x)+f2(x)
}
retfun
}
Run Code Online (Sandbox Code Playgroud)
在两个函数上测试funadd时,它可以完美运行.但是,当我尝试评估Reduce命令的结果时,我收到错误
Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
Run Code Online (Sandbox Code Playgroud)
有趣的是,Reduce这不起作用......请注意"手动减少"有效:
f <- function(x) x^2
g <- function(x) x^3
h <- function(x) x^4
x <- runif(3)
f(x)+g(x)+h(x)
#[1] 0.9760703 0.1873004 0.1266966
funadd(funadd(f,g),h)(x)
#[1] 0.9760703 0.1873004 0.1266966
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用此:
funadd2 <- function(...){
function(x) Reduce(`+`, lapply(list(...), function(f) f(x)))
}
funadd2(f,g,h)(x)
#[1] 0.9760703 0.1873004 0.1266966
Run Code Online (Sandbox Code Playgroud)
编辑:这是发生了什么:
看一下源代码Reduce,我们可以看到它(大致)有一个循环这样做:
init <- f
init <- funadd(init, g)
Run Code Online (Sandbox Code Playgroud)
如果有更多元素(init <- funadd(init, h),...),则继续.
这会导致引用f在第一次循环迭代中丢失:
init(x)
# Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
Run Code Online (Sandbox Code Playgroud)
这是因为f1在最后一个retfun指向自己:
identical(environment(init)$f1, init, ignore.environment=FALSE)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)
正如@Vincent所知,这也可以通过强制参数来解决,即通过制作避免懒惰评估的本地副本f1和f2:
funadd3 <- function(f1,f2){
f1.save <- f1
f2.save <- f2
retfun <- function(x){
f1.save(x)+f2.save(x)
}
retfun
}
Reduce(funadd3, list(f,g,h))(x)
# [1] 0.9760703 0.1873004 0.1266966
Run Code Online (Sandbox Code Playgroud)
强制评估参数可以解决问题.
funadd <- function(f1,f2){
force(f1)
force(f2)
retfun <- function(x){
f1(x)+f2(x)
}
retfun
}
r <- Reduce( funadd, list( f, g, h ) )
r(x) # works
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
605 次 |
| 最近记录: |