Flaky S4 метод отправки - PullRequest
       2

Flaky S4 метод отправки

1 голос
/ 24 июня 2019

Я проверял, могу ли я поддерживать модели, приспособленные с использованием пакета cplm в emmeans , и я столкнулся с очень странным поведением метода terms. Вот пример:

library(emmeans)
library(cplm)

data(mtcars)

m <- cpglm(mpg ~ cyl + disp + hp, data = mtcars)

Функция emmeans:::recover_data.lm, похоже, обещала работать правильно. Он просто вызывает метод terms объекта и передает его другим функциям. Однако это не работает:

> emmeans:::recover_data.lm(m)
 Error in slot(x, name) : 
  no slot of name "terms" for this object of class "cpglm" 

Копая дальше, я проверяю, что terms() работает в глобальной среде:

> terms(m)
mpg ~ cyl + disp + hp
... (remaining lines excluded) ...

Однако это не работает в recover_data.lm:

> debug(emmeans:::recover_data.lm)
> emmeans:::recover_data.lm(m)
    ...

Browse[2]> terms(object)
Error in slot(x, name) : 
  no slot of name "terms" for this object of class "cpglm"

Browse[2]> getMethod("terms", "cpglm")
Error in getMethod("terms", "cpglm") : 
  no method found for function 'terms' and signature cpglm

Однако ...

Browse[2]> getMethod("terms", "cplm")  ## cpglm inherits from cplm
Method Definition:

function (x, ...) 
attr(x@model.frame, "terms")
    ... etc. ...

Browse[2]> methods("terms")
[1] terms,ANY-method  terms,cplm-method terms.default*    terms.formula*    terms.gls*       
[6] terms.merMod*     terms.terms*     
see '?methods' for accessing help and source code

Browse[2]> selectMethod("terms", "cpglm")
Method Definition:

function (x, ...) 
attr(x@model.frame, "terms")
    ... etc. ...

Итак, в пространстве имен для emmeans я могу убедиться, что мы «знаем», что существует terms метод для cpglm объектов, и мы можем найти его через selectMethod(), но не через getMethod() или просто позвонив terms(). Это очень странно, тем более что документация для selectMethod обещает, что она должна работать:

Функция selectMethod() возвращает метод, который будет выбран для вызова функции f, если аргументы имеют классы, как указано signature.

Наконец, я могу убедиться, что это как-то связано с конфликтом при отправке методов S3:

> stats::terms(m)
Error in slot(x, name) : 
  no slot of name "terms" for this object of class "cpglm"

Есть ли способ заставить мой пакет emmeans работать правильно, когда есть сочетание методов S3 и S4; в частности, искать методы S4 перед методами S3?

1 Ответ

1 голос
/ 25 июня 2019

Из записи документации в Methods_for_S3:

Причины определения методов S3 и S4 следующие:

  1. Один метод S4 не будет виден, если универсальная функция S3 вызывается напрямую. Это будет иметь место, например, если какая-то функция вызывает unique () из пакета, который не делает эту функцию универсальной в S4.

Пакет cplm экспортировал метод S4 для terms, но не один для S3, который вы можете увидеть здесь . Это автоматически делает terms универсальным S4, когда вы присоединяете cplm. Тем не менее, emmeans вызывает S3 универсальный от stats, и это то, что вызывает проблему.

Вы можете обойти это, определив универсальный S3 в глобальной среде, который отправляет универсальному S4:

terms.cpglm <- function(x, ...) {
    cplm::terms(x, ...)
}

но вы должны сообщить сопровождающему cplm, что он должен определить методы S3 и S4, если он преобразует универсальный S3 в S4.

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