定义R功能列表

时间:2018-12-02 11:20:41

标签: r function lazy-evaluation

我正在尝试在循环中定义函数列表,如下所示:

rr <- list(); ss <- list(list(1,2),list(3,4))

for (i in 1:length(ss)) {
  A <- ss[[i]][1]
  B <- ss[[i]][2]
  print(paste("A, B:", A, ",", B))
  rr[[i]] <- function () { force(B); B }
}

print语句给出:

[1] "A, B: 1 , 2"
[1] "A, B: 3 , 4"

...这就是我想要的!但是,当我尝试使用这些函数时,我得到了错误的答案(我认为AB的计算是延迟的,等到实际调用该函数以获取其值时):

> environment(rr[[1]])$A
[[1]]
[1] 3

> rr[[1]]()
[[1]]
[1] 4

> environment(rr[[2]])$A
[[1]]
[1] 3

> rr[[2]]()
[[1]]
[1] 4

如何重写上面的for循环,以便每个函数rr[[i]]都有自己的内部参数集,以后的{{1 }}函数定义?

2 个答案:

答案 0 :(得分:1)

编辑:我下面的解决方案可能会对某人有所帮助,因此我将其保留在后头,但是user2554330 answer对于我的使用来说是一个更好的解决方案-情况。


啊哈!在this answer的帮助下,我找到了答案:

rr <- list(); ss <- list(list(1,2),list(3,4))

for (i in 1:length(ss)) {
  rr[[i]] <- function(x){}
  body(rr[[i]]) <- parse(text={
    paste("(", ss[[i]][[1]], "<= x) && (x <=", ss[[i]][[2]], ")")
  })
}

> rr[[1]](1.5) # within range [1,2]
[1] TRUE
> rr[[1]](2.5)
[1] FALSE

> rr[[2]](3.5) # within range [3,4]
[1] TRUE
> rr[[2]](4.5)
[1] FALSE

答案 1 :(得分:1)

记住fortunes::fortune(106)。当然,有更好的方法可以做到这一点。

一种方法是使“函数工厂”捕获值。例如,

make_fn <- function(A, B) {
  force(A)
  force(B)
  function(x) A <= x & x <= B  
}

那么您的循环将是

for (i in 1:length(ss)) {
  A <- ss[[i]][1]
  B <- ss[[i]][2]
  print(paste("A, B:", A, ",", B))
  rr[[i]] <- make_fn(A, B)
}

经过编辑以添加评论注释:此处与force()的区别如下:force()适用于promise,即函数的参数。在您的示例中,B从来都不是任何函数的参数,因此它绝不是一个承诺,并且force(B)除了返回其值外什么也不做。在我的回答中,ABmake_fn的参数,因此在求值时它们是promise,而force()导致求值它们的表达式和值。固定。