什么是嵌套`eval`的环境和外壳?

Kon*_*lph 5 environment eval r

背景

我正在为lambdas创建一个快捷方式,因为重复使用了function (…) …我的代码.作为补救措施,我正在尝试使用其他语言(如Haskell)启发的替代语法,只要在R. Simplified中可以实现,我的代码如下所示:

f <- function (...) {
    args <- match.call(expand.dots = FALSE)$...
    last <- length(args)
    params <- c(args[-last], names(args)[[last]])

    function (...)
        eval(args[[length(args)]],
             envir = setNames(list(...), params),
             enclos = parent.frame())
}
Run Code Online (Sandbox Code Playgroud)

这允许以下代码:

f(x = x * 2)(5)       # => 10
f(x, y = x + y)(1, 2) # => 3
Run Code Online (Sandbox Code Playgroud)

等等

当然,真正的目的是将它与高阶函数1一起使用:

Map(f(x = x * 2), 1 : 10)
Run Code Online (Sandbox Code Playgroud)

问题

不幸的是,我有时必须嵌套高阶函数然后它停止工作:

f(x = Map(f(y = x + y), 1:2))(10)
Run Code Online (Sandbox Code Playgroud)

产生"错误eval(expr, envir, enclos):x找不到对象".概念上等效的代码使用function而不是f工作.此外,其他嵌套方案也有效:

f(x = f(y = x + y)(2))(3) # => 5
Run Code Online (Sandbox Code Playgroud)

我怀疑罪魁祸首是嵌套f在地图内部的父环境:它是顶级环境而不是外部环境f.但我不知道如何解决这个问题,这让我感到困惑的是上面的第二个场景是有效的.相关问题(例如此问题)提出了在我的案例中不适用的解决方法.

显然,我对R中环境的理解存在差距.我想要的是什么?


1当然这个例子可以简单地写成(1 : 10) * 2.真正的应用程序是更复杂的对象/操作.

flo*_*del 5

答案是附加parent.frame()到输出函数的环境:

f <- function (...) {
    args <- match.call(expand.dots = FALSE)$...
    last <- length(args)
    params <- c(args[-last], names(args)[[last]])

    e <- parent.frame()

    function (...)
        eval(args[[length(args)]],
             envir = setNames(list(...), params),
             enclos = e)
}
Run Code Online (Sandbox Code Playgroud)

希望有人可以解释为什么这有效而不是你的.随意编辑.