我在循环中定义函数,并试图强制评估循环变量,而不必携带私有环境。

示例:一组函数handlers$h1handlers$h2,...,handlers$h6只是通过1、2,...,6传递给另一个函数,如下所示:

handlers <- list()
for (i in 1:6) {
    handlers[[paste0('h', i)]] <- function () {
        message(i) # <-- example
    }
}


因此handlers$h1()应该是消息1,handlers$h2()应该是消息2,...

而是,所有函数都返回6,即i的当前值。

为了解决这个问题,我可以将闭包用作specified in this question

msg <- function(i) {
    force(i)
    function () { message(i) }
}

for (i in 1:6) {
    handlers[[paste0('h', i)]] <- msg(i)
}


现在,每个功能都可以按预期工作,但是每个功能必须具有自己的环境:

handlers$h1
# function () { message(i) }
# <environment: 0x9342b80>


如何使handlers$h1打印function () { message(1) },即求值i并将其直接替换为定义,从而消除对环境的需要?

我能想到的唯一方法是:


使用eval(我不喜欢这样做);
手动写出每个定义,并直接替换1-6(在这种情况下,只有6个函数,但通常不能扩展)可以很好地写出来

最佳答案

以下是一些使用body<-的方法

您可以使用bquote

handlers <- list()

for (i in 1:6) {
  handlers[[paste0('h', i)]] <- function () {}
  body( handlers[[paste0('h', i)]]) <- bquote(message(.(i)))
}

handlers$h1
## function ()
##   message(1L)


substitute

for (i in 1:6) {
  handlers[[paste0('h', i)]] <- function () {}
  body( handlers[[paste0('h', i)]]) <- substitute(message(i), list(i=i))
}

09-27 13:24