Ссылка на пакет и функцию в качестве аргументов в другой функции - PullRequest
5 голосов
/ 18 октября 2019

Я пытаюсь найти методы для конкретных функций в разных пакетах R. Например, methods(broom::tidy) вернет все методы для функции tidy в пакете broom. Для моей текущей проблемы было бы лучше, если бы у меня была функция methods в другой функции, например: f1 <- function(x,y){ methods(x::y) }

(я удалил другие части кода, которые не имеют отношения к моей проблеме.) Однакокогда я запускаю функцию следующим образом:

f1 <- function(x,y){ methods(x::y)}
f1(broom,tidy)

Я получаю ошибку

Ошибка в loadNamespace (имя): нет пакета с именем 'x'

Если я пытаюсь изменить его так, чтобы он только менял функцию, но оставил пакет таким же, я получаю похожую ошибку:

f2 <- function(y){  methods(broom::y)}
f2(tidy)

Ошибка: 'y' не экспортируемый объектиз 'namespace: broom'

Как я могу получить имя пакета и функции для правильной оценки в функции? Эта текущая проблема связана с тем, когда r пытается оценить / заменить значения в функции?

1 Ответ

5 голосов
/ 18 октября 2019

Обе функции :: и methods() используют нестандартную оценку для работы. Это означает, что вам нужно быть немного умнее с передачей значений в функции, чтобы заставить его работать. Вот один из методов

f1 <- function(x,y){ 
  do.call("methods", list(substitute(x::y)))
}
f1(broom,tidy)

Здесь мы используем substitute() для расширения и значения x и y, которые мы передаем в поиск пространства имен. Это решает часть ::, которую вы можете увидеть с помощью

f2 <- function(x,y){ 
  substitute(x::y)
}
f2(broom,tidy)
# broom::tidy

Нам нужна замена, потому что вполне может быть пакет x с функцией y. По этой причине переменные не раскрываются при использовании ::. Обратите внимание, что :: - это просто оболочка для getExportedValue(), если в противном случае вам понадобится извлекать значения из пространств имен с использованием символьных значений.

Но есть еще один улов: methods() не оценивает свои параметры, этоиспользует необработанное выражение для поиска методов. Это означает, что нам на самом деле не нужно значение broom::tidy, мы должны передать это буквальное выражение. Так как нам нужно вычислить замену, чтобы получить выражение, которое нам нужно, нам нужно построить вызов с do.call(), чтобы оценить substitute и передать это выражение на methods()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...