2015-04-24 2 views
3

Если я объявить функцию, я могу сослаться на предыдущие аргументы:Путаница аргументы функции в R

blah <- function(a=1, b=a) { print(sprintf("a=%d, b=%d", a, b)) } 

Выход:

> blah(10) 
[1] "a=10, b=10" 
> blah(10, b=30) 
[1] "a=10, b=30" 

Однако следующий не работает:

> blah(a=10, b=a) 
Error in sprintf("a=%d, b=%d", a, b) : object 'a' not found 

Фактически, это более или менее то, что вы ожидаете; так почему объявление blah <- function(a=10, b=a) работает? Почему область здесь различна, чем когда я вызываю функцию?

Кроме того, почему ошибка появляется только при вызове sprintf? Почему он не вызывает ошибку сразу при вызове функции? Я запутался.

Edit:

Здесь объяснить мое замешательство. Когда я объявляю функцию, параметры не оцениваются. R имеет ленивую оценку, и переменные оцениваются по мере необходимости. Рассмотрим следующее:

> blah <- function(a=1, b=print("foo")) { print("So far, so good") ; print(b) } 
> 

Не было оценки. Я в настоящее время называют бла:

> blah() 
[1] "So far, so good" 
[1] "foo" 
[1] "foo" 

Первое утверждение в функции вычисляется, затемprint("foo"). Тем не менее, в то время, а есть - мы имеем это в области функций. Так почему бы b=a не оценить? Мы уже находимся в функции, когда это происходит, а было объявлено.

Edit 2:

Перед тем, как перейти к неправильным выводам, обратите внимание, что ссылаясь на предыдущий аргумент в объявлении функции в R perfectly fine из-за ленивую оценку АиРа. Я не понимаю, почему он работает в объявлении функции, но не тогда, когда я звоню. Я не говорю, что он должен или не должен работать, просто задаваясь вопросом о базовой механике обзора.

+0

У вас нет переменной «a» в вашей среде. Вот почему вы получаете эту ошибку. Например, если вы определяете первый «a = 150», он работает. «a» в вашей функции и «a» в вашей среде - разные объекты. –

+0

Так почему это работает, когда я объявляю функцию? – January

+0

Ну, да, попробуй это для себя. – January

ответ

2

Там это разница между тем, где два выражения вычисляются. Когда вы вызываете функцию, параметры оцениваются в текущей области.Когда вы определяете функцию, параметры оцениваются в пределах области действия. Обычно это поведение, которое вы хотите.

Поэтому, когда вы вызываете функцию, ожидается, что вы контролируете все значения, переданные функции. Вам не нужно знать, какие переменные используются внутри функции. С ленивыми вычислениями, эта конструкция также работает:

blah <- function(a=1, b=x) { 
    x < a+10 
    print(sprintf("a=%d, b=%d", a, b)) 
} 
blah(1) 

так пытается вызвать

blah(1, b=x+5) 

делает еще меньше смысла, потому что технически вы не должны даже знать, переменная x существует внутри функции.

В этом примере вы можете увидеть разницу в окружении. Здесь мы используем parent.frame(), чтобы получить среду, из которой была вызвана функция.

myenv <- function() parent.frame() 
foo <- function(a=myenv()) { 
    print(environment()) 
    print(a) 
} 
foo() 
# <environment: 0x10c8b1948> 
# <environment: 0x10c8b1948> 
foo(a=myenv()) 
# <environment: 0x10bd85ad8> 
# <environment: R_GlobalEnv> 

Поэтому, когда функция работает со значением параметра по умолчанию, она работает в той же среде, что и сама функция. Когда вы явно передаете параметр, он запускается в среде, когда он был вызван (что в данном случае является глобальной средой).

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

+0

Спасибо, это был ответ на мой вопрос. – January

2

Когда вы делаете:

> blah(a=10, b=a) 

Вы говорите: У меня есть значение 10в моей глобальной envrionment и я назначу его аргумент a. У меня есть переменная aв моей глобальной среде и присваиваю ее значение аргументу b. Переменная a полностью отличается от аргумента a функции! Если переменная a не определена, и вы хотите отдать ее функции, R будет кричать.

Вы будете иметь точно такую ​​же ошибку, выполнив:

> blah(a=10, b=nonExistingVariable) 
Error in sprintf("a=%d, b=%d", a, b) : object 'NonExistingVariable' not found 
+0

Это то, что я безуспешно пытался объяснить. –

+0

Я думаю, что последняя строка кода более ясна, чем любое объяснение, я сокращу свою. –

+0

Хорошо, так почему же работает 'blah <- function (a = 1, b = a)'? – January