класс expr и exprs различаются в Rlang в R!Зачем? - PullRequest
0 голосов
/ 25 мая 2018

Я не уверен, если это было задано здесь, но я очень смущен здесь.Я читаю эту удивительную книгу Хадли Уикхэма "Advanced R" от здесь .

Здесь описана функция под названием cement, я немного ее изменил и пытаюсь понятьit.

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 не может сработать, если нет, как это правильно?

Iпрошу прощения за слишком длинные предложения, мой родной язык не английский, поэтому, если есть что-то глупое, пожалуйста, дайте мне знать, я исправлю это.Я надеюсь, что это не дубликат, я попытался найти ответ, но не смог найти его самостоятельно.

Спасибо за любую помощь.

R Версия : 3.4.2 rlang : 0,2,0

1 Ответ

0 голосов
/ 23 августа 2018

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(), затем объединяет результаты водна строка.

2a) Теперь, когда у нас работает 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"
...