Подтвердить что ты не робот

Почему наследование метода убивает дополнительные аргументы?

Я хочу установить несколько флагов в свой общий (до вызова UseMethod(), я знаю это много:)), а затем использовать и/или обновлять эти флаги в методах.

Так же:

g <- function(x) {
  y <- 10
  UseMethod("g")
}
g.default <- function(x) {
  c(x = x, y = y)
}
g.a <- function(x) {
  y <- 5  # update y from generic here
  NextMethod()
}

Это работает при прямом переходе к методу по умолчанию:

g(structure(.Data = 1, class = "c"))  # here y is never updated
# x  y 
# 1 10 

Но когда я прохожу через NextMethod(), y таинственно исчезает:

g(structure(.Data = 1, class = "a"))  # here y is updated, but cannot be found
# Error in g.default(structure(.Data = 1, class = "a")) : 
#  object 'y' not found

Я выяснил, как исправить это, просто проходя вокруг y много:

f <- function(x, ...) {
  y <- 10
  UseMethod("f")
}
f.default <- function(x, ..., y = 3) {
  c(x = x, y = y)
}
f.a <- function(x, ...) {
  y <- 5
  NextMethod(y = y)
}

что дает

f(structure(.Data = 1, class = "c"))
# x y 
# 1 3 
f(structure(.Data = 1, class = "a"))
# x y 
# 1 5 

Мой вопрос: Почему NextMethod() в приведенном выше g().* -example убивает дополнительный y аргумент?

Я думал, что все точки UseMethod() и NextMethod() должны были передавать любые и все объекты от вызова к вызову, без необходимости вручную передавать их:

NextMethod работает, создавая специальный кадр вызова для следующего метода. Если новые аргументы не заданы, аргументы будут одинаковыми по числу, порядку и имени как текущим методу, но их значения будут promises, чтобы оценить их имя в текущем методе и среде.

Я особенно смущен тем, что UseMethod(), похоже, проходит y, но NextMethod() этого не делает.

4b9b3361

Ответ 1

Как заметил @Roland, это поведение документировано:

Из help("UseMethod") абзац о примечаниях UseMethod() (выделено мной):

UseMethod создает новый вызов функции с аргументами, согласованными по мере их появления. Любые локальные переменные, определенные до вызова UseMethod, сохраняются (в отличие от S). Любые утверждения после вызова метода UseMethod не будут оцениваться по мере того, как UseMethod не возвращается.

Соответствующий параграф о NextMethod() (уже цитированный выше) просто отмечает:

NextMethod работает, создавая специальный кадр вызова для следующего метода. Если новые аргументы не заданы, аргументы будут одинаковыми по числу, порядку и имени как текущим методу, но их значения будут promises для оценки их имени в текущем методе и среде. Любые именованные аргументы, сопоставляемые с... обрабатываются специально: они либо заменяют существующие аргументы с тем же именем, либо присоединяются к списку аргументов. Они передаются в качестве обещания, которое было предоставлено в качестве аргумента для текущей среды. (S делает это иначе!) Если они были оценены в текущей (или предыдущей среде), они остаются оцененными. (Это сложная область и может быть изменена: см. Проект "Определение языка R".)

Короче, тогда UseMethod() делает что-то особенное и необычное: оно переходит к локальным переменным. NextMethod(), как обычно, не делает этого.

UseMethod() является исключением, а не NextMethod().