Расширение функции применения до S3 (например, с помощью печати или графика)

Я работаю над любимым проектом в R, который создает собственный класс S3 с именем groupr. Я написал несколько функций с точечной записью (print.groupr, subset.groupr), как описано в Учебник Hadley, но я хочу расширить функцию apply и не могу найти способ сделать это.

Как показано в руководстве, пакет pryr предоставляет подсказку. Я вижу, что функции subset и print представляют собой разные типы функций, например:

> pryr::ftype(subset)
[1] "s3"      "generic"
> pryr::ftype(apply)
[1] "function"

Кроме того, функция subset печатает это в терминале:

function (x, ...) 
UseMethod("subset")
<bytecode: 0x115f0ab88>
<environment: namespace:base>

Но функция apply выводит весь свой исходный код. Я полагаю, что понимаю, почему это происходит — функции print, subset, plot и т. д. — это функции S3, а apply — скучная старая нормальная функция, но я не вижу никакого способа расширить функцию apply. без «перезаписи» базовой функции. Например, UseMethod("apply") указывает вызов функции на мое пространство имен groupr при загрузке пакета.

Кто-нибудь знает, как решить эту проблему? А именно, семейство функций apply не является объектами S3 и не может быть расширено с помощью записи через точку. Кто-нибудь знает, как писать функции apply.myclass, apply.myotherclass?


person Alex Thompson    schedule 30.03.2018    source источник
comment
apply не является общим. Я считаю, что в этом и заключается разница, должно быть неудобно писать к нему методы. Как вы сказали, вам придется перезаписать базовую функцию.   -  person Rui Barradas    schedule 30.03.2018


Ответы (1)


Вы в основном там; вам нужно перезаписать исходный apply, но используйте общую функцию, которая вызывает оригинал по умолчанию. Таким образом, ваш пакет будет иметь три функции: apply, которая будет новой универсальной, apply.default, которая будет вызывать base::apply, и ваша новая apply.myclass. Когда ваш пакет загружен, ваша версия apply будет выше в пути поиска, так что привыкнете. Я уверен, что видел, как это делают пакеты, но сейчас не могу привести пример.

Я бы, однако, спросил, стоит ли это того; будут ли ваши пользователи действительно возражать, например, что версия для groupr будет apply_groupr? Мы все знаем, что делает apply и что используется в матрицах. Действительно ли эта новая функциональность достаточно похожа, чтобы иметь одно и то же имя? То есть, если я увижу apply(my_groupr, 2, mean), не запутаюсь ли я, потому что my_groupr не является матрицей?

person Aaron left Stack Overflow    schedule 30.03.2018
comment
Круто, я считаю, что это имеет смысл. Мой план, по сути, такой же, как вы описываете — дайте ему другое имя — потому что он позволяет избежать этой ерунды пути поиска. Однако мне кажется, что apply является достаточно общим, чтобы его можно было переписать как общую функцию S3. Например, apply.matrix, apply.list, apply.vector могут заменить apply, lapply и vapply. Это всего лишь векторизованный способ зацикливания. Я думаю, что это просто первый раз, когда я столкнулся со странными особенностями самого R (еще одно непоследовательное применение точечной записи, например, с t.data.frame) - person Alex Thompson; 30.03.2018
comment
Говоря о странных особенностях R, вы видели The R Inferno? - person Aaron left Stack Overflow; 30.03.2018
comment
Ах, это, да, я видел это, но еще не прочитал. Кажется, у кого-то есть чувство юмора по этому поводу. - person Alex Thompson; 30.03.2018