R: Обещание не может найти объект - PullRequest
0 голосов
/ 05 июля 2018

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

foo <- function(a, b = length(a)) {
  b
}

foo(a = c(1, 2))
[1] 2

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

foo(a = c(1, 2), b = length(a))
Error in foo(a = c(1, 2), b = length(a)) : object 'a' not found

Я думал, что обещание b = length(a) должно быть оценено внутри функции, где известно a, но, видимо, этого не происходит. Может кто-нибудь объяснить, где проблема и как я мог бы сделать

foo(a = c(1, 2), b = length(a))

работать

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Насколько я понимаю, когда вы явно даете аргументы функции, поведение по умолчанию заключается в оценке указанных аргументов в среде, в которой они были заданы, , а не в среде выполнения функции (как @ ответ Axeman детали).

Можно обойти это (если вы должны - это другое дело). Вы можете использовать комбинацию substitute() (для захвата неоцененного аргумента) и eval(), чтобы изменить среду, в которой оценивается аргумент. Здесь мы явно оцениваем b в среде выполнения foo:

foo <- function(a, b = length(a)) {
  eval(substitute(b), env = environment())
}

(Из-за значений по умолчанию в eval() было бы достаточно просто написать eval(substitute(b)). Но иногда приятно быть явным; вот так, гораздо более очевидно, что мы меняем среду оценки.)

Теперь следующее не выдаст ошибку:

foo(a = c(1, 2), b = length(a))
#> [1] 2

Однако , если вы решите пойти по этому пути, вы должны быть очень явными при документировании такой функции, чтобы аргумент b оценивался в среде выполнения. Например, что должно произойти, когда a присутствует как в среде, в которой задан аргумент, так и в среде выполнения? Это может быть неожиданным поведением, если оно плохо документировано (и источником трудно диагностируемых ошибок, даже если оно хорошо документировано).

a <- 1:10
foo(a = c(1, 2), b = length(a))
#> [1] 2

Для получения более подробной информации об оценке (и подводных камнях), вы можете проверить главу Evaluation в Advanced R .

Создано в 2018-07-05 пакетом Представ (v0.2.0).

0 голосов
/ 05 июля 2018

При наборе foo(a = c(1, 2), b = length(a)), a должен исходить из вызывающей среды, а не из функциональной среды. Вам нужно будет использовать:

x <- 1:2
foo(a = x, b = length(x))

Или используйте аргумент функции:

foo <- function(a, fun = length) { fun(a) }

Цитировать Хэдли :

С технической точки зрения, неоцененный аргумент называется обещанием, или (реже) гром. Обещание состоит из двух частей:

  • Выражение, которое приводит к отложенному вычислению. (Доступ к нему можно получить с помощью replacestitute (). См. Нестандартную оценку для подробнее.)

  • Среда, в которой было создано выражение и где его следует оценивать.

Вы правильно поняли, что аргументы - это обещания, и они не оцениваются, пока не понадобятся. Но обещание включает в себя среду, в которой оно было создано, что в данном случае в глобальной среде.

...