当eval'ing时,match.call在错误的环境中调用

时间:2013-05-01 13:31:43

标签: r eval substitution

我尝试使用以下语义实现函数let

> let(x = 1, y = 2, x + y)
[1] 3

...这在概念上与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()))
}

注意嵌套的eval,外部用于评估实际表达式,而内部用于评估参数。

不幸的是,后一种评估发生在错误的背景下。尝试使用检查当前帧的函数调用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

我想过提供父框架作为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)
}

这会产生相同的错误。这引出了一个问题:match.call究竟是如何评估的?为什么这不起作用?并且,如何使这项工作?

1 个答案:

答案 0 :(得分:6)

这次改写会解决你的问题吗?

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