Класс 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"
Другие вопросы по тегам