Как запоминать функцию при запуске пакета в R

Я работаю над пакетом R, который обертывает вызовы API. Чтобы уменьшить количество фактических вызовов и ускорить процесс, я запомнил функцию, выполняющую вызов API. Для этого я создал следующую функцию, которая позволяет установить каталог кеша:

memoise_fromJSON <- function(cache_dir = tempdir()) {
  memoise::memoise(jsonlite::fromJSON,
                   cache = memoise::cache_filesystem(cache_dir))
}

Для создания мемоизированной функции я использую

memoised_fromJSON <- memoise_fromJSON()

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

.onLoad <- function(libname, pkgname) {
  memoised_fromJSON <- my_package:::memoise_fromJSON()
}

но мне все еще нужно бежать memoised_fromJSON <- memoise_fromJSON() чтобы заставить его работать.

Итак, мои вопросы:

  1. Есть ли возможность запоминать функцию при запуске пакета?
  2. Если да, как я могу сохранить функцию таким образом, чтобы она не отображалась в глобальной среде?

Думаю, вопросы как-то связаны. Правильно ли я понимаю, что моя попытка с.onLoad() не работает, потому что он создает мемоизированную функцию в среде .onLoad()?


PS: Я знаю, что не могу изменить cache_dirпри загрузке пакета, но я хочу установить разумное значение по умолчанию, которое позволит начать работу без лишних слов. Однако при этом сохраняется возможность при необходимости изменить каталог кеша.

3 ответа

Вы выполняете локальное задание внутриonLoad функция.

И вы не можете просто выполнить (пакетное) глобальное назначение, поскольку пространство имен пакета заблокировано. Что ты можешь сделать, это

  1. Создайте новую среду с помощью new.env(parent = parent.env(environment()) (параметр гарантирует, что эта среда находит объекты, определенные в пространстве имен вашего пакета).
  2. Назначьте мемоизированные функции внутри этой среды.
  3. attachсреда. Это, как правило, не одобряется и фактически принесет вам красную карточку от CRAN, если вы попытаетесь отправить ее. Фактически, ваш.onLoadфункция не должна вызыватьattachпоскольку пользователь может захотеть использовать ваш пакет, не прикрепляя его. Но я думаю, что это законно, если вы сделаете это в.onAttach скорее, чем .onLoad. Боюсь, что сопровождающие CRAN могут не согласиться; опять же, есть приоритет для пакетов CRAN, которые вызываютattach при определенных обстоятельствах, например {devtools}.

У вас может быть мемоизированная функция в вашем пакете, нет необходимости .onLoad() колдовство:

Имейте в любом из ваших скриптов:

      memoised_fromJSON <- memoise::memoise(
  jsonlite::fromJSON, 
  cache = memoise::cache_filesystem(cache_dir))

Вы можете добавлять объекты в свое пространство имен во время .onLoad, хотя здесь вам это не нужно, и способ сделать это:

      .onLoad <- function(libname, pkgname) {
  your_object <- your_object_builder()
  ns <- asNamespace(pkgname)
  namespaceExport(ns, "your_object ")
}

Если вам нужно экспортировать его, используя {roxygen2}, вам необходимо иметь в ваших скриптах:

      #' your title
#' @whatever tags you need
#' @export
your_object <- NULL

И почему бы не объявить функцию memoized напрямую в исходниках R?

      #' Memoised version of [jsonlite::fromJSON]
#' @inherit jsonlite::fromJSON
#' 
#' @export
memoised_fromJSON <- memoise::memoise(jsonlite::fromJSON,
                                      cache = memoise::cache_filesystem(tempdir()))

Это должно выполнить работу без каких-либо примечаний или предупреждений при проверке R CMD.

Другие вопросы по тегам