Проблемы с передачей аргументов с помощью callNextMethod() в R

Мой вопрос:

Почему callNextMethod() не передает аргументы следующему методу, как ожидалось?

Ситуация:

Скажем, у меня есть два иерархических класса foo и bar (bar является подклассом foo), для которых у меня есть метод foobar, который может выполнять диспетчеризацию для обоих классов (т. е. имеет методы для обоих классов).

Кроме того, метод для (под)класса bar вызывает метод для foo после некоторых вычислений с callNextMethod().

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

setClass("foo", representation(x = "numeric"))
setClass("bar", contains = "foo")

setGeneric("foobar", function(object, ...) standardGeneric("foobar"))

setMethod("foobar", "foo", function(object, another.argument = FALSE, ...) {
    print(paste("in foo-method:", another.argument))
    if (another.argument) object@x^3
    else object@x^2
})

setMethod("foobar", "bar", function(object, another.argument = FALSE, ...) {
    print(paste("in bar-method:", another.argument))
     object@x <- sqrt(object@x)
    callNextMethod()
})

Описание проблемы.
Аргументы передаются не так, как ожидалось, но значения по умолчанию берутся из определения метода. В частности, в первом методе аргумент такой, как указано в вызове (TRUE), однако в следующем методе он меняется на FALSE.

o1 <- new("bar", x = 4)

foobar(o1, another.argument = TRUE)

дает

[1] "in bar-method: TRUE"
[1] "in foo-method: FALSE"
[1] 4

Я хочу, чтобы another.argument передавалось следующему методу, чтобы он также был TRUE в вызове метода foo.


Из ?callNextMethod я получаю, что он должен работать так, как ожидалось (т. е. именованный аргумент передается так, как он есть в вызове):

Для формального аргумента, скажем x, который появляется в исходном вызове, в следующем вызове метода есть соответствующий аргумент, эквивалентный x = x. Фактически это означает, что следующий метод видит те же фактические аргументы, но аргументы оцениваются только один раз.


Мой второй вопрос: как передать другой аргумент следующему методу. (Мне бы очень хотелось сохранить аргументы по умолчанию в обоих методах)


person Henrik    schedule 25.08.2011    source источник
comment
Я в тупике. Если вы не получили здесь никаких ответов, вы можете попробовать это в списке рассылки r-devel...   -  person Ben Bolker    schedule 25.08.2011


Ответы (1)


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

> selectMethod(foobar, "bar")
Method Definition:

function (object, ...) 
{
    .local <- function (object, another.argument = FALSE, ...) 
    {
        print(paste("in bar-method:", another.argument))
        object@x <- sqrt(object@x)
        callNextMethod()
    }
    .local(object, ...)
}

Signatures:
        object
target  "bar" 

defined "bar" 

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

setGeneric("foobar",
    function(object, another.argument=FALSE, ...) standardGeneric("foobar"),
    signature="object")

или явно передать аргументы callNextMethod

setMethod("foobar", "bar", function(object, another.argument = FALSE, ...) {
    print(paste("in bar-method:", another.argument))
     object@x <- sqrt(object@x)
    callNextMethod(object, another.argument, ...)
})
person Martin Morgan    schedule 25.08.2011
comment
Еще один отличный ответ от вас на вопрос S4. Большое спасибо. - person Henrik; 26.08.2011
comment
Спасибо. Почему мы не можем просто назвать это ошибкой, а не ошибкой или неосмотрительностью...? Поскольку у меня болит мозг, пытаясь понять, почему наблюдаемое поведение не противоречит тому, что указано в документации? (S4 ранит мой мозг в лучшие времена.) - person Ben Bolker; 26.08.2011
comment
Я полностью согласен (но не с той частью S4, которая вредит мозгу. Мне действительно нравится S4). - person Henrik; 26.08.2011
comment
«ошибка» подразумевает некоторую непреднамеренную оплошность, и у меня нет такого понимания мозга автора. Поэтому я полностью убрал приговор. Я бы рекомендовал отчет о R-devel, иначе человек, способный изменить это, не знает о проблеме. - person Martin Morgan; 26.08.2011
comment
Я поддерживаю предложение отчета R-devel. ИМХО, это является ошибкой, потому что я не могу придумать какой-либо правдоподобной интерпретации документации, которая соответствовала бы поведению кода. (Тем не менее, можно исправить ошибку, изменив документацию...) - person Ben Bolker; 26.08.2011
comment
Вчера я написал об этом сообщение в R-devel (thread.gmane. org/gmane.comp.lang.r.devel/28806), но ответов пока нет. Буду держать вас в курсе, если будут новости. - person Henrik; 31.08.2011