R范围:在没有本地环境的情况下强制执行变量替换

mat*_*fee 4 scope r

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

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

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

所以handlers$h1()应该消息1,handlers$h2()应该消息2,...

相反,所有函数返回6,当前i.

为了解决这个问题,我可以使用此问题中指定的闭包

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

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

现在每个函数都按预期工作,每个函数都必须携带自己的环境:

handlers$h1
# function () { message(i) }
# <environment: 0x9342b80>
Run Code Online (Sandbox Code Playgroud)

我怎样才能使handlers$h1打印function () { message(1) },即评估i并直接将其替换为定义,从而消除对环境的需求?

我能想到的唯一方法是:

  • 使用eval(我不喜欢做的事);
  • 直接用1-6替换手写出每个定义(在这种情况下只有6个函数,但通常不可扩展)

mne*_*nel 7

以下是一些使用的方法 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)
Run Code Online (Sandbox Code Playgroud)

要么 substitute

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