S3: изменить аргумент по умолчанию перед вызовом NextMethod () - PullRequest
0 голосов
/ 02 апреля 2020

В функции S3 generi c я бы хотел изменить аргумент функции перед вызовом NextMethod(). В качестве отправной точки я просмотрел «1002 * # 44 * 1003» «Список пожеланий для R» Хенрика Бенгтссона. Следующий фрагмент взят оттуда и соответствует его предложению о том, как изменить аргумент перед вызовом NextMethod().

x <- structure(NA, class = "A")
expected <- list(x = x, a = 3)

foo <- function(x, a) UseMethod("foo")

foo.A <- function(x, a) {
  a <- a + 1
  NextMethod()
}

foo.default <- function(x, a) {
  list(x = x, a = a)
}

identical(foo(x, a = 2), expected)
#> [1] TRUE
identical(foo(x, 2), expected)
#> [1] TRUE

. Теперь меня озадачило следующее поведение, когда изменяемый аргумент имеет значение по умолчанию.

bar <- function(x, a) UseMethod("bar")

bar.A <- function(x, a = 2) {
  a <- a + 1
  NextMethod()
}

bar.default <- function(x, a = 2) {
  list(x = x, a = a)
}

identical(bar(x, a = 2), expected)
#> [1] TRUE
identical(bar(x, 2), expected)
#> [1] TRUE
identical(bar(x), expected)
#> [1] FALSE

Может кто-нибудь помочь мне понять, что здесь происходит? Любые идеи о том, как заставить аргумент по умолчанию работать (кроме явного вызова bar.default())?

1 Ответ

1 голос
/ 02 апреля 2020

Я не уверен, насколько реалистично c эта установка, но проблема с ней в том, что вызов bar(x) означает, что вы звоните bar.A(x), затем (через NextMethod()) вы звоните bar.default(x), а не bar.default(x, a = 3), как вы могли бы ожидать.

Обходной путь - специально передать a в качестве параметра в NextMethod. Проблема, с которой вы столкнетесь при этом, заключается в том, что если пользователь не называет второй параметр, то bar.default сгенерирует, потому что ему дается 3 параметра вместо двух (x, 2 и a = 3). Вы можете обойти это, включив параметр ... в bar.default, чтобы неназванные параметры игнорировались.

x <- structure(NA, class = "A")
expected <- list(x = x, a = 3)

bar <- function(x, ...) UseMethod("bar")

bar.A <- function(x, a = 2) {
  a <- a + 1
  NextMethod("bar", x, a = a)
}

bar.default <- function(x, ..., a = 2) {
  list(x = x, a = a)
}

identical(bar(x, a = 2), expected)
#> [1] TRUE
identical(bar(x, 2), expected)
#> [1] TRUE
identical(bar(x), expected)
#> [1] TRUE

Создано в 2020-04-02 пакетом prex (v0.3.0)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...