Смущен...()?

В другом вопросеsapply(substitute(...()), as.character) был использован внутри функции для получения имен, переданных в функцию. as.character часть звучит нормально, но что на земле делает ...() делать?

Это недействительный код за пределами substitute:

> test <- function(...) ...()
> test(T,F)
Error in test(T, F) : could not find function "..."

Еще несколько тестов:

> test <- function(...) substitute(...())
> test(T,F)
[[1]]
T

[[2]]
F

> test <- function(...) substitute(...)
> test(T,F)
T

1 ответ

Решение

Вот эскиз почему ...() работает так, как работает. Я добавлю больше деталей и ссылок позже, но это касается ключевых моментов.

  1. Перед выполнением замены на любом из его компонентов, substitute() сначала разбирает R оператор.

  2. ...() разбирает объект вызова, тогда как ... разбирает имя объекта.

  3. ... это специальный объект, предназначенный только для использования в вызовах функций. Как следствие, код C, который реализует замену, принимает специальные меры для обработки ... когда он найден в объекте вызова. Подобные меры предосторожности не принимаются, когда ... происходит как символ. (Соответствующий код в функциях do_substitute, substitute, а также substituteList (особенно последние два) в R_SRCDIR/src/main/coerce.c.)

Итак, роль () в ...() должен вызывать синтаксический анализ оператора как объекта вызова (так называемого языка), чтобы подстановка возвращала полностью расширенное значение точек. Может показаться удивительным, что ... заменяется даже тогда, когда он находится за пределами (), но: (a) вызовы хранятся внутри как объекты, подобные списку, и (b) соответствующий код C, кажется, не делает различий между первым элементом этого списка и последующими.


Просто примечание: для изучения поведения substitute или классы различных объектов, я считаю полезным установить небольшую песочницу, например:

f <- function(...) browser()
f(a = 4, 77, B = "char")
## Then play around within the browser
class(quote(...))  ## quote() parses without substituting
class(quote(...()))
substitute({...})
substitute(...(..., X, ...))
substitute(2 <- (makes * list(no - sense))(...))
Другие вопросы по тегам