2017-02-14 8 views
7

Итак, я работаю над пакетом R, который использует классы S3, и было бы очень хорошо, если бы я мог использовать sample как метод для одного из моих классов. Однако base уже заявляет sample как не S3 функции, так что я интересно это:Неплохой стиль для переопределения базовых функций, отличных от S3, как функции S3 в пакете R?

Является ли это плохой стиль переопределять не-S3 base функции, такие как sample как функции S3? И может ли это повредить пользователям моего пакета?

Путь можно переопределить sample и по-прежнему держать base функции работы является:

sample.default <- base::sample 
sample <- function(x, ...) { 
    UseMethod("sample") 
} 
# This allows me to define a new sample method for my_special_class 
sample.my_special_class <- function(...) {...} 

Но что я уверен, является ли это вызовет какие-либо проблемы или пространство имен вопросы, например, при загрузке другие пакеты. Я также заметил, что не многие пакеты переопределить sample, например, dplyr использует sample_n и igraph использует sample_, и я подумал, что может быть какая-то причина для этого ...

+0

Если вы еще этого не сделали, возможно, вы можете придумать свой собственный класс и определить «sample.yourclassname» для обработки ваших классов. Таким образом, вы сохраняете согласованность использования общих функций. –

+0

@ RomanLuštrik: Это не работает, потому что 'base :: sample' не является общим. Если это было общее, нет причин переопределять его в вашем пакете; вы просто зарегистрируете свой метод. –

+0

@ JoshuaUlrich Бах, ты избил меня. Просто проверил функции за секунды до вашего сообщения. Ты прав. Вернуться к доске для рисования. –

ответ

9

ли или нет это плохо «стиль» является прежде всего на основе мнения. Но Writing R Extensions, Section 7.1 - Adding new generics рассказывает вам, как добавлять новые дженерики, маскирующие базовую базу/рекомендуемые функции. Тем не менее, предложенное вами решение явно предостерегал против в этом разделе:

... пакет может взять на себя функцию в базовом пакете и сделать его родовое что-то вроде

foo <- function(object, ...) UseMethod("foo") 
foo.default <- function(object, ...) base::foo(object) 

Более ранние версии этого руководства предлагается назначить foo.default <- base::foo. Это не очень хорошая идея, так как она фиксирует базовую функцию во время установки и может быть изменена по мере исправления или обновления R.

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

Не многие пакеты переопределяют sample, потому что это обычно не рекомендуется маскировать базовые/рекомендуемые функции. Это создает возможность для пользователей получать различное поведение на верхнем уровне в зависимости от того, загружен ли ваш пакет.

Одна вещь, которую вы, конечно же, хотите избежать, - это маскирование родового в базовом/рекомендованном (или очень используемом) пакете. Это может предотвратить отправку метода на верхнем уровне, вызывая головные боли для пользователей, которые ожидают, что общий тип работы (например, dplyr::lag).

+0

Если я правильно понимаю руководство, CRAN предлагает вам определить ' sample.default <- function (x, ...) base :: sample (x, ...) 'и считает это допустимым. – Benjamin

+0

@Benjamin Почему бы вам не просто создать свой собственный класс и расширить общий для обработки класса? –

+0

@ RomanLuštrik Я считаю, что это то, что пытается сделать Расмус Баас. Вопрос, который он задает, - это что делать с 'base :: sample', когда он переопределяет' sample <- function (x, ...) UseMethod ("sample") '(пожалуйста, поправьте меня, если я что-то не понимаю) – Benjamin