2014-10-27 1 views
7

ПочемуИспользуя те же имена аргументов для функции, определенные внутри другой функции

f <- function(a) { 
    g <- function(a=a) { 
     return(a + 2) 
    } 
    return(g()) 
} 
f(3) # Error in a + 2: 'a' is missing 

вызывают ошибку? Это как-то связано с аргументом a = a, особенно с тем, что имена переменных одинаковы. Что именно происходит?

Вот некоторые подобные фрагменты кода, которые работают, как и ожидалось:

f <- function(a) { 
    g <- function(a) { 
     return(a + 2) 
    } 
    return(g(a)) 
} 
f(3) # 5 

f <- function(a) { 
    g <- function(g_a=a) { 
     return(g_a + 2) 
    } 
    return(g()) 
} 
f(3) # 5 

g <- function(a) a + 2 
f <- function(a) g(a) 
f(3) # 5 

ответ

6

Проблема заключается в том, что, as explained in the R language definition:

The default arguments to a function are evaluated in the evaluation frame of the function.

В вашем первом блоке кода, при вызове g() без каких-либо аргументов, он падает обратно на его значение по умолчанию a, который a. Оценив, что в «фрейме функции» (т. Е. Среде, созданной вызовом g()), он находит аргумент, имя которого соответствует символу a, а его значение равно a. Когда он ищет значение этого a, он находит аргумент, имя которого соответствует этому символу и значение которого равно a. Когда ...

Как вы можете видеть, что вы застряли в петле, которая является то, что сообщение об ошибке пытается сказать вам:

Error in g() : 
    promise already under evaluation: recursive default argument reference or 
earlier problems? 

Вашей второй попытки, которая вызывает g(a) работает, как вы ожидали, потому что вы поставляется аргумент, и, as explained in the same section of R-lang:

The supplied arguments to a function are evaluated in the evaluation frame of the calling function.

Там он находит символ a, который связан с любым значением, которое вы передали формальному аргументу внешней функции a, и все хорошо.

4

Проблема является a=a часть. Аргумент не может быть его собственным значением по умолчанию. Это круговая ссылка.

Этот пример может помочь прояснить, как это работает:

x <- 1 
f <- function(a = x) { x <- 2; a } 
f() 
## [1] 2 

Обратите внимание, что a не имеет значения по умолчанию 1; он имеет значение по умолчанию 2. Он выглядит сначала в самой функции по умолчанию. Аналогичным образом a=a приведет к тому, что a будет его собственным значением по умолчанию, которое является круговым.

+1

и сообщение об ошибке в R 3.1.1 является 'Ошибка в g(): Обещание уже оценивается: рекурсивный аргумент аргумента по умолчанию или более ранние проблемы? ' – Roland

+0

Это гораздо полезнее, чем сообщение об ошибке, которое я видел (Ошибка: 'a' отсутствует). У меня есть R версии 3.0.2 (2013-09-25) - "Frisbee Sailing" – Adrian

Смежные вопросы