Класс expr и exprs различаются в Rlang в R! Зачем?
Я не уверен, если это было задано здесь, но я очень смущен здесь. Я читаю эту удивительную книгу Хэдли Уикхэма под названием Advanced R.
Есть функция называетсяcement
что было описано здесь, я немного изменил и пытаюсь понять это.
library(rlang)
cement1 <- function(x) {
dots <- expr(x)
print(class(dots))
#paste(expr_name(x))
}
cement2 <- function(y,z) {
dots <- exprs(y,z)
print(class(dots))
#paste(purrr::map(dots, expr_name), collapse = " ")
}
Запуск вышеcement1
без каких-либо параметров возвращает мне класс точек как "имя".
Тем не менее, когда я запускаюcement2
функция с дополнительным параметром, класс возвращает "список", {просто помещая класс (expr(x)), возвращает "имя", тогда как класс (exprs(x)) возвращает "список"}.
Я не собираюсь думать об этом, потому что это печатает другой класс, возвращенный expr
а такжеexprs
, Единственное различие, о котором я думал, что знал о них, было то, что один имеет дело с одним параметром, другой имеет дело с несколькими параметрами, но я могу ошибаться, я мог пропустить некоторые детали.
Исходная проблема: Итак, все началось с запуска этих двух функций по отдельности, удалив раздел комментариев в коде для обоихcement1
а такжеcement2
Когда я запускаю функции, ниже приведены результаты, возвращаемые ими:
cement1(Hello) #Returns , Error in type_of(.x) : object 'Hello' not found
cement2(Hello) #Works very well and returns, [1] "y z"
Поэтому я попытался найти причину, почемуcement1
не удалось, а затем напечатал их классы, и тогда я понял,expr
а также exprs
вернуть разные классы.
Мой вопрос:
1) Они задуманы, если да, то почему? Или я совершаю ужасную ошибку, которую сейчас не вижу.
2) лиcement1
не может сработать, если нет, как правильно?
Я прошу прощения за слишком длинные предложения, мой родной язык не английский, поэтому, если есть что-то глупое, пожалуйста, дайте мне знать, я исправлю это. Я надеюсь, что это не дубликат, я пытался найти ответ, но не смог найти самостоятельно.
Спасибо за любую помощь.
Версия R: 3.4.2rlang:0.2.0
1 ответ
1) Да, возвращаемые значения expr
а также exprs
отличаются по дизайну. От ?expr
страница справки:
enexpr() и expr() фиксируют одно необработанное выражение.
enexprs() и exprs() захватывают список необработанных выражений, включая выражения, содержащиеся в
...
,
2) expr_name()
ожидает выражение в кавычках, например, что производится expr()
, Итак, вам нужно изменить ваш cement1
звонить expr_name()
на dots
не x
, Вы также можете удалить paste
потому что вы ничего не объединяете.
cement1 <- function(x) {
dots <- expr(x)
# print(class(dots)) ## Commented out for clarity
expr_name(dots) ## The input to expr_name is now effectively expr(x)
}
cement1( Hello )
# "x"
Ваша функция cement2
в основном звонки expr_name()
на каждый элемент списка, возвращаемый exprs()
, а затем объединяет результаты в одну строку.
2а) Теперь, когда мы получили ваш cement1
работая, мы можем улучшить его дальше. В настоящее время функция не использует входной аргумент x
, expr()
просто захватывает неоцененное выражение, и это выражение всегда будет x
Независимо от того, что вы называете своим аргументом:
cement1.1 <- function( completelyIgnoredName ) {
dots <- expr(x)
expr_name(dots)
}
cement1.1( Hello )
# "x"
Однако, если вы замените expr()
с enexpr()
функция заменит выражение, предоставленное в качестве аргумента функции, и получит вместо этого следующее:
cement1.2 <- function(x) {
dots <- enexpr(x)
expr_name(dots)
}
cement1.2( Hello )
# "Hello"