2
fa <- function(x){x+1}
fb <- function(x){x-1}

f1 <- function(x, y){f(x)^y}

f2 <- function(x, ab, y){
   if(ab == 'a'){
     f <- fa
   } else {
     f <- fb
   }
   f1(x, y)
}

f2(0, 'a', .5)
Error in f1(x, y) : could not find function "f"

以上不起作用,因为f未在f1' 环境中定义。

什么是使这项工作的好方法?那

  • 避免将全局环境中的所有内容传递给f2's 环境
  • 避免必须重新定义内部函数f2(这会很麻烦,并为复制/粘贴错误创造机会)

定义某种“子全局”环境,并将我希望每个人都使用的东西放在这个环境中,然后让每个函数都能够从“子全局”访问东西是否有意义?然后以某种方式确保子全局始终是全局的严格子集?如果明智的话,我会怎么做?

4

1 回答 1

8

以上不起作用,因为fa并且fb未在f2' 环境中定义。

不——他们。错误是完全不同的:

f1 <- function(x, y){f(x)^y}

在这里,您使用的是未定义的变量f,这是一个错误。

您在. _ _ 但是,这与因为并且不共享它们的局部变量无关。如果您想将's传递给,则需要将其作为参数传递。ff2f1f1f2f2ff1

顺便说一句,您的变量名称如此相似的事实使这比必要的复杂。如果您将代码更改为以下等效代码,则问题会变得更加清晰:

plus1 = function (x) x + 1
minus1 = function (x) x - 1

f_exp = function (x, y) g(x) ^ y

plusminus_exp = function (x, ab, y) {
    if (ab == 'a')
        f = plus1
    else
        f = minus1
    f_exp(x, y)
}

plusminus_exp(0, 'a', .5)
# Error in f_exp(x, y) : could not find function "g"

这是修复:

f_exp = function (x, y, g) g(x) ^ y
f_exp(x, y, f)

或者,如果您在f_exp内部多次调用plusminus_exp,您可以使用一些更高级的抽象来创建函数构建器:返回另一个函数的函数:

make_f_exp = function (f) {
    force(f)
    function (x, y)
        f(x) ^ y
}

plusminus_exp = function (x, ab, y) {
    f = if (ab == 'a') plus1 else minus1
    f_exp = make_f_exp(f)
    f_exp(x, y)
}

这使得f_exp可插入但隔离效果以避免引入全局可修改状态。这是函数式编程语言的标准代码,但在函数式语言之外不太常见,因此对某些人来说有点令人惊讶。

于 2016-11-23T16:26:14.430 回答