我尝试通过https://adv-r.hadley.nz/index.html,这似乎是一个很好的来源,但我似乎仍然停留在基础知识上。
我想编写一个函数“my_fun(boolex, probs)”,它将用户定义的表达式“boolex”作为输入,并在 my_fun 内部的环境“e”中对其进行求值。我想允许用户编写自己的函数“user_fun”,它应该能够调用“e”中定义的函数 P(x),因为它访问 user_fun 事先不知道的 my_fun 参数。
这是我尝试过的(这是一个玩具示例,但我想要实现的结构就在那里):
library(rlang)
my_fun <- function(boolex, probs){
e <- env(caller_env(),
.probs=probs,
P=function(i){
.probs[as.character(enexpr(i))]
}
)
env_print(e)
print(enexpr(boolex))
eval(enexpr(boolex), e)
}
user_fun <- function(x, y){
x>=P(y)
}
my_fun(
user_fun(0.4, C),
c(A=0.1, B=0.2, C=0.3, D=0.4)
)
但是,我收到错误消息:找不到函数 P。我猜测 user_fun 中的 P 会更早绑定到 P,但即便如此,我也希望它位于 caller_env() 中并且可用。
定义函数时,它们保存对定义它们的环境的引用。这使得词法作用域成为可能。因此,函数首先在函数体中查找变量,然后在定义它们的环境中查找变量,然后在该环境的父环境中查找。它们不一定解析调用环境中的变量。由于您在全局环境中定义了
user_fun
,因此它将在全局环境中解析不存在的 P()
。您可以使用 environment()
函数 查看函数在何处解析自由变量
environment(user_fun)
<environment: R_GlobalEnv>
您可以通过
environment<-
分配不同的环境,但如果该函数也使用全局范围内的自由变量,您将遇到解决这两个问题的问题。
您可以在此处阅读有关词法作用域的更多信息:https://adv-r.hadley.nz/functions.html?q=lexical#lexical-scoping