R懒惰求值悖论(R的bug?)

10

我有多个函数处理可能缺失的参数。

例如,我有

mainfunction <- function(somearg) {
    mytest(somearg)
    fun <- function() { subfunction(somearg) }
    fun()
}

具有趣味性的一点是,mytest(somearg)与参数的唯一交互是它测试参数是否不存在。
mytest = function(somearg) {
    print(missing(somearg))
}

subfunction再次测试其是否丢失并相应地进行处理:

subfunction = function(somearg) {
    if (missing(somearg))
        somearg = NULL
    else
        somearg = matrix(somearg, cols = 2)
    # somearg is used here…
}

使用 matrix(somearg, cols = 2) 的时候,somearg 缺失会导致此操作失败,并显示:

argument "somearg" is missing, with no default

在调试过程中,我发现以下情况: 1)在 mainfunction 开始时,missing(somearg) 返回 TRUE。 2)在 mytest 中,missing(somearg) 返回 TRUE。 3)在 subfunction 中,missing(somearg) 返回 FALSE。 因此,虽然实际上缺少了参数 somearg,但是却进入了 matrix 分支,导致操作失败。

1
我猜问题在于你没有直接调用 subfunction,而是从一个嵌套函数中调用它,这会在参数 somearg 上创建一个闭包。似乎闭包无法处理缺少的参数。我不确定这是一个错误还是“按设计来的”:在 fun 中,somearg 不是一个参数,它是一个普通变量,因此不能缺失。 - Konrad Rudolph
6
请查看文档:“目前 missing 只能在定义参数的函数的立即体中使用,不能在嵌套函数或 local 调用的体中使用。” - Roland
3
尽管“missing”也可以使用,但在这种情况下,我觉得将“NULL”作为明确的缺失值更容易;虽然这会使函数文档稍微丑陋一些,但使用is.null(arg)进行测试时就不会出现任何问题。 - Ben Bolker
1
顺便说一下,@BenBolker如果您可以把我做错的地方以及如何规避这些问题的方法结合在一个简短的答案中,我会很高兴给您打上对勾:D - flying sheep
1
或者@Roland(当然,我在评论中只能提到一个人(‽)) - flying sheep
显示剩余3条评论
1个回答

1

@BenBolker 的方式:

mainfunction <- function(somearg = NULL) {
    mytest(somearg)
    fun <- function() { subfunction(somearg) }
    fun()
}

mytest = function(somearg) {
    print(is.null(somearg))
}

subfunction = function(somearg) {
    if (is.null(somearg))
        somearg = 1:10
    else
        somearg = matrix(somearg, ncol = 2)
   somearg
}

另一种方法是使用显式的缺失参数。
mainfunction <- function(somearg) {
    is_missing <- missing(somearg)
    mytest(is_missing)
    fun <- function() { subfunction(somearg, is_missing) }
    fun()
}
mytest = function(x) {  print(x) }
subfunction = function(somearg, is_arg_missing) {
    if (is_arg_missing)
        somearg = 1:10
    else
        somearg = matrix(somearg, ncol = 2)
   somearg
}

第三种方法,使用普通的缺失参数传递:

    mainfunction <- function(somearg) {
        is_missing <- missing(somearg)
        mytest(somearg)
        fun <- function() { 
          if (is_missing) subfunction() else 
              subfunction(somearg) 
        }
        fun()
    }

    mytest = function(somearg) {
        print(missing(somearg))
    }

    subfunction = function(somearg) {
        if (missing(somearg))
            somearg = 1:10
        else
            somearg = matrix(somearg, ncol = 2)
       somearg
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接