Kon*_*lph 9 eval r substitution
我尝试let使用以下语义实现一个函数:
> let(x = 1, y = 2, x + y)
[1] 3
Run Code Online (Sandbox Code Playgroud)
...在概念上有点类似于substitute语法with.
以下代码几乎可以工作(例如上面的调用工作):
let <- function (...) {
args <- match.call(expand.dots = FALSE)$`...`
expr <- args[[length(args)]]
eval(expr,
list2env(lapply(args[-length(args)], eval), parent = parent.frame()))
}
Run Code Online (Sandbox Code Playgroud)
注意嵌套eval,外部用于评估实际表达式,而inner用于评估参数.
不幸的是,后一种评估发生在错误的背景下.当尝试let使用检查当前帧的函数调用时,这变得很明显,例如match.call:
> (function () let(x = match.call(), x))()
Error in match.call() :
unable to find a closure from within which 'match.call' was called
Run Code Online (Sandbox Code Playgroud)
我想过提供父框架作为评估环境eval,但这不起作用:
let <- function (...) {
args <- match.call(expand.dots = FALSE)$`...`
expr <- args[[length(args)]]
parent <- parent.frame()
eval(expr,
list2env(lapply(args[-length(args)], function(x) eval(x, parent)),
parent = parent)
}
Run Code Online (Sandbox Code Playgroud)
这会产生相同的错误.这引出了我的问题:如何match.call评估?为什么这不起作用?而且,我该如何使这项工作?
这个重写会解决你的问题吗?
let <- function (expr, ...) {
expr <- match.call(expand.dots = FALSE)$expr
given <- list(...)
eval(expr, list2env(given, parent = parent.frame()))
}
let(x = 1, y = 2, x + y)
# [1] 3
Run Code Online (Sandbox Code Playgroud)