R:对函数内部变量的内容进行硬编码

R: hard code the content of a variable inside a function

提问人:Dominique Makowski 提问时间:6/8/2021 更新时间:6/8/2021 访问量:326

问:

我想使用存储在变量中的值创建一个函数,但以某种方式粘贴该变量的“内容”而不是变量调用,以便一旦重新分配变量,函数就不会更改。

有没有一种优雅的方法可以做到这一点?

var <- 3
f <- function(x) var + x

f(1)
#> [1] 4

var <- 1

f(1)  # I would like the output to stay the same, i.e., the function to be "fixed" after its creation
#> [1] 2

创建于 2021-06-08 由 reprex 包 (v1.0.0)

R 函数 命名空间 NSE

评论

1赞 jay.sf 6/8/2021
为什么不使用参数?var=f <- function(x, var) var + x;var <- 123;f(1, var=3)
0赞 Onyambu 6/8/2021
输出应该保持不变是什么意思?您需要 2 或 4?

答:

2赞 MrFlick 6/8/2021 #1

在 R 中,您将使用以下方法之一创建闭包。您可以定义一个本地环境并复制到那里var

f <- local({var; function(x) var + x})

或者你可以用内联函数做类似的事情

f <- local({var; function(x) var + x})

或者,您可以将该版本拆分为生成器函数

make_f <- function(var) function(x) var + x
f <- make_f(var)

所有这些都会冻结函数内部的值。varf

还可以编写一个帮助程序函数,该函数将更明确地说明环境创建

freeze_var <- function(fun, ..., .env=environment(fun)) {
  mc <- match.call(expand.dots = FALSE)
  dnames <- sapply(mc$..., deparse)
  fenv <- new.env(parent=.env)
  list2env(setNames(list(...), dnames), envir = fenv)
  environment(fun) <- fenv
  fun
}

然后你可以用它来用任何变量包装任何函数

var <- 3
f <- function(x) var + x
ff <- freeze_var(f, var)

f(1)
# [1] 4
ff(1)
# [1] 4

var <- 1
f(1)
# [1] 2
ff(1)
# [1] 4
1赞 Roland 6/8/2021 #2

您可以根据以下语言进行计算:

var <- 3
f <- function(x) var + x
body(f)[[2]] <- var

f
#function (x) 
#3 + x

f(1)
#> [1] 4

var <- 1
f(1)
#[1] 4
0赞 Onyambu 6/8/2021 #3

我不太确定输出保持不变的确切含义:

在这里,我们可以做到:

f <- local({
        a <- new.env()
        if(!exists('z', a)) a$z<-var
        function(x)x+a$z})
var <- 3
f(1)
#[1] 4
var <- 1
f(1)
#[1] 4  # Did not change (BUT WHY WOULD YOU WANT THIS BEHAVIOUR?)

为什么需要相同的输出?您宁愿在函数中使用值 3

f <- function(x) x + 3

甚至锁定变量以防止对其进行任何更改。即对变量的任何更改都会引发错误

var <- 3
lockBinding('var', globalenv())
f <- function(x) x + var

var <- 1# will throw an error.