автоматическое перенаправление функций - PullRequest
0 голосов
/ 13 февраля 2012

язык R.

У меня есть пара файлов:

utilities.non.foo.R
utilities.foo.R
utilities.R

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

По сути, utilities.foo.R содержит множество функций, для которых требуется пакет foo. Функции здесь называются functionname.foo.

Я собираюсь начать делиться этим кодом с внешними соавторами, у которых нет этого пакета или Linux, поэтому я написал файл utilities.non.foo.R, который содержит все функции в utilities.foo.R, кроме зависимости от пакет foo был удален. Все эти функции называются functionname.non.foo.

Файл utilities.R имеет целую кучу для каждой функции:

functionname <- function(...) {
    if ( fooIsLoaded() ) {
        functionname.foo(...)
    } else {
        functionname.non.foo(...)
    }
}

Идея состоит в том, что нужно всего лишь загрузить utilities.R, и если у вас окажется пакет foo (например, мои внутренние сотрудники), вы будете использовать этот бэкэнд. Если у вас нет foo (внешних соавторов), вы будете использовать бэкэнд не-foo.

Мой вопрос: есть ли способ сделать перенаправление для каждого имени функции без явного написания вышеуказанного бита кода для каждого отдельного имени функции?

Это напоминает мне о том, как (например) существует метод print, print.table, print.data.frame и т. Д., Но пользователю нужно только использовать print, и какой метод используется, выбирается автоматически.

Мне бы хотелось, чтобы, кроме method.class, было бы больше похоже на method.depends_on_which_package_is_loaded.

Есть ли способ избежать написания функции перенаправления для каждой функции в моем файле utilities.R?

Ответы [ 3 ]

2 голосов
/ 13 февраля 2012

Как говорит Дирк, просто используйте пакет.В этом случае поместите все новые функции *.non.foo в новый пакет, который также называется foo.Распространите это foo среди ваших сотрудников вместо вашей собственной версии.Таким образом, ваш код утилиты может быть просто

functionname <- function(...) functionname.foo(...)

без каких-либо проверок.

1 голос
/ 13 февраля 2012

Вот идея: напишите функцию, которая устанавливает f в f.foo или f.non.foo.Его можно вызывать в цикле для всех функций в данном пространстве имен (или для всех функций, чье имя заканчивается на .foo).

dispatch <- function(s) {
 if ( fooIsLoaded() ) {
    f <- get( paste(s, "foo",     sep=".") )
  } else {
    f <- get( paste(s, "non.foo", sep=".") )
  }
  assign( s, f, envir=.GlobalEnv ) # You may want to use a namespace
}
f.foo     <- function() cat("foo\n")
f.non.foo <- function() cat("non-foo\n")
fooIsLoaded <- function() TRUE
dispatch("f")
f()
fooIsLoaded <- function() FALSE
dispatch("f")
f()

Более простое решение - присвоить одинаковые имена обеим функциям, но поместите их в разные пространства имен / пакеты.

0 голосов
/ 13 февраля 2012

Это звучит довольно неэффективно и не элегантно, но как насчет

funify = function(f, g, package="ggplot2") {
 if(paste("package:", package, sep="") %in% search()) f else 
  { message("how do you intend to work without ", package) ; g}
}
  detach(package:ggplot2)
  foo = funify(paste, function(x) letters[x])
  foo(1:10)
  library(ggplot2)
  foo = funify(paste, function(x) letters[x])
  foo(1:10)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...