R ленивый парадокс оценки (R ошибка?)

У меня есть несколько функций, которые передают аргументы, которые могут отсутствовать.

например. я

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

с интересным аспектом, что единственное взаимодействие mytest(somearg) с аргументом arg состоит в том, что он проверяет отсутствие аргумента:

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…
}

кикер состоит в том, что при отсутствии somearg это не работает: matrix(somearg, cols = 2) throws

аргумент "somearg" отсутствует, без значения по умолчанию

во время отладки я обнаружил следующее:

  • в начале mainfunction, missing(somearg) возвращает TRUE
  • в mytest, missing(somearg) возвращает TRUE
  • в subfunction, missing(somearg) возвращает FALSE (!!!!)

поэтому ветвь matrix попадает, но на самом деле somearg отсутствует, поэтому он терпит неудачу...

ват.

Ответ 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
}

Третий способ, используя простой пропущенный переход arg:

    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
    }