Ошибка экспорта при перезаписи примитивов с помощью S3 в пакете R

Я пытаюсь создать метод S3 в своем пакете под названием dimnames. Это примитив в R, но в моем пакете должен быть S3 с таким же именем.

У меня есть следующий файл dimnames.r

#' S3 overwriting primitive
#'
#' @param x  object
#' @export
dimnames = function(x) {
    UseMethod("dimnames")
}

#' title
#'
#' @export
dimnames.data.frame = function(x) {
    dimnames.default(x)
}

#' title
#'
#' @export
dimnames.list = function(x) {
    lapply(x, dimnames)
}

#' title
#'
#' @export
dimnames.default = function(x) {
    message("in S3 method")
    base::dimnames(x)
}

Затем я создаю из него пакет (в R=3.3.2):

> package.skeleton("rpkg", code_files="dimnames.r")
> setwd("rpkg")
> devtools::document() # version 1.12.0

И затем проверьте пакет

R CMD build rpkg
R CMD check rpkg_1.0.tar.gz

Я получаю следующий вывод (среди других сообщений):

Предупреждение: объявленный метод S3 'dimnames.default' не найден

Предупреждение: объявленный метод S3 'dimnames.list' не найден

При загрузке пакета и проверке его содержимого dimnames.data.frame экспортируется, а dimnames.default и dimnames.list - нет. Это не имеет смысла для меня. Насколько я понимаю, экспорт я задекларировал правильно. Кроме того, мне нравится файл NAMESPACE:

S3method(dimnames,data.frame)
S3method(dimnames,default)
S3method(dimnames,list)
export(dimnames)

Почему это не работает и как это исправить?

(Бонусные баллы: зачем мне #' title в реализациях S3, когда они не нужны с roxygen=5.0.1?)


person Michael Schubert    schedule 29.11.2016    source источник


Ответы (1)


Методы S3 экспортируются только в том случае, если желательно, чтобы пользователь имел к ним прямой доступ. Если они всегда должны вызываться через дженерик, тогда нет необходимости их экспортировать.

Проблема с R CMD check, вероятно, связана с определением собственного универсального для dimnames. Обычно просто определяют методы и используют примитивный дженерик уже в R. Удалите dimnames дженерик из dimnames.r.

Не должно быть проблем с добавлением методов для новых классов, но у вас могут возникнуть проблемы при попытке переопределить функциональность dimnames для существующих классов, которые R dimnames обрабатывает сам.

person G. Grothendieck    schedule 05.12.2016
comment
Кажется, вы правы: (1) dimnames является универсальным в базе, (2) вы не можете перезаписывать дженерики S3 в пакетах, (2) предоставление дополнительных реализаций работает для пользовательских классов (dimnames(structure(1, class="foo"))), но не по умолчанию или в случае списка. - person Michael Schubert; 06.12.2016