Подтвердить что ты не робот

Как импортировать только одну функцию из другого пакета без загрузки всего пространства имен

Предположим, что я разрабатываю пакет под названием foo, который хотел бы использовать функцию description из пакета memisc. Я не хочу импортировать полное пространство имен memisc, потому что:

  • Плохо
  • memisc переопределяет базовую функцию aggregate.formula, которая разбивает несколько вещей. Например, example(aggregate) терпит неудачу.

В пакет входят следующие файлы:

ОПИСАНИЕ

Package: foo
Version: 0.0
Title: Foo
Imports:
    memisc
Collate:
    'foo.R'

NAMESPACE

export(bar)
importFrom(memisc,description)

R/foo.R

##' bar function
##'
##' @param x something
##' @return nothing
##' @importFrom memisc description
##' @export

`bar` <- function(x) {
    description(x)
}

Я думаю, что использование importFrom не загрузило бы полное пространство имен memisc, а только namespace::description, но это не так. Начиная с ванили R:

R> getS3method("aggregate","formula")
## ... function code ...
## <environment: namespace:stats>
R> library(foo)
R> getS3method("aggregate","formula")
## ... function code ...
## <environment: namespace:memisc>
R> example(aggregate)
## Fails

Итак, знаете ли вы, как я могу импортировать функцию description из memisc, не получив aggregate.formula в моей среде?

4b9b3361

Ответ 1

Вы не можете.

Если вы объявите memisc в поле Imports:, пространство имен будет загружено при загрузке пакета и экспортированные объекты будут найдены вашим пакетом. (Если вы укажете его в Depends:, пространство имен будет загружено и привязано к пути поиска, что сделает экспортируемые объекты доступными для любого кода.)

Часть загрузки пространства имен регистрирует методы с общим. (Я смотрел, но не мог найти каноническую документацию, в которой говорится об этом, я буду обращать внимание на то, что функции объявлены как методы S3 в файле NAMESPACE в качестве доказательства.) Определенные методы сохраняются с общим и имеют видимость общей функции (или, возможно, пространства имен общих функций).

Как правило, пакет будет определять метод либо для генерируемого им родового, либо для определенного им класса. Объектная система S3 не имеет механизма формального определения класса S3 (или того, какой пакет создавал класс), но общая идея заключается в том, что если пакет определяет функции, которые возвращают объект с этим атрибутом класса (и это единственный пакет, который), этот класс - это класс пакета. Если выполняется одно из этих двух условий, проблем не будет. Если общий тип определен в пакете, его можно найти только в том случае, если пакет прикреплен; если класс определен в пакете, объекты этого класса будут существовать (и, следовательно, отправляться), если пакет будет прикреплен и использован.

В примере memisc не выполняется. Оболочка aggregate определяется в пакете stats, а объект formula также определяется в пакете stats (на основе этого пакета, определяющего as.formula, [.formula и т.д.). Поскольку он не является ни memisc generic и memisc, эффекты можно увидеть ровно (и отправленный метод), если memisc просто загружен, но не подключен.

Для другого примера этой проблемы, но с reorder.factor, см. Фактор переупорядочения дает разные результаты в зависимости от того, какие пакеты загружены.

В общем, не рекомендуется добавлять методы к дженерикам, для которых пакет не контролирует ни объект, ни общий; дважды, если он переопределяет метод в базовом пакете; и вопиюще, так что если это не обратная совместимая функция с существующей функцией в основных пакетах.

В вашем примере вам может быть лучше скопировать код для memisc::describe в ваш пакет, хотя этот подход имеет свои собственные проблемы и оговорки.