В чем разница между sym () и parse_expr () в пакете rlang?

Используя пакет rlang, мне интересно, в чем разница между sym() и parse_expr(). Рассмотрим, например, следующие выражения:

ex1 = sym('a')
ex2 = parse_expr('a')

Они оба возвращаются

a

identical(ex1, ex2)
[1] TRUE

Предположим, теперь мне нужен вопрос:

ex3 = quo(!!sym('a'))
ex4 = quo(!!parse_expr('a'))

В обоих случаях результат:

<quosure>
expr: ^a
env:  global

identical(ex3, ex4)
[1] TRUE

Тем не менее, по некоторым причинам следующие два не совпадают.

ex5 = quo(!!sym('a - b'))
ex6 = quo(!!parse_expr('a - b'))

По-видимому, они идентичны, поскольку оба возвращаются:

<quosure>
expr: ^a - b
env:  global

Пока что,

identical(ex5, ex6)
[1] FALSE

Итак, мой вопрос: в чем разница между sym() и parse_expr()? Что делает один, чего не может другой? И почему ex5 очевидно похоже на ex6, но identical(ex5, ex6) возвращает ЛОЖЬ?


person Rtist    schedule 03.05.2018    source источник


Ответы (2)


Ссылаясь на мой ответ на это вопрос:

Символ - это способ ссылки на объект R, в основном имя объекта. Таким образом, sym похож на as.name в базе R. parse_expr, с другой стороны, преобразует некоторый текст в выражения R. Это похоже на parse в базе R.

Выражения могут быть любым кодом R, а не только кодом, который ссылается на объекты R. Таким образом, вы можете проанализировать код, который ссылается на объект R, но вы не можете превратить какой-то случайный код в sym, если объект, на который ссылается код, не существует.

Как правило, вы будете использовать sym, когда ваша строка ссылается на объект (хотя parse_expr также будет работать), и использовать parse_expr, когда вы пытаетесь проанализировать любой другой код R для дальнейшей оценки.

В вашем первом примере a может быть как именем, которое ссылается на объект, так и выражением, поэтому преобразование его в sym или parse_expr практически означало бы одно и то же. Фактически, R неявно преобразует выражение в sym, когда это возможно, как показано в вашем первом примере.

Однако в вашем последнем примере a - b действительно предназначено для выражения (если только у вас нет объекта R со странным названием a - b). Распечатав следующее, вы увидите, что использование sym vs parse_expr для кода R , который должен быть выражением, а не объектом R, дает два разных результата:

> quo(!!sym('a - b'))
<quosure: global>
~`a - b`

> quo(!!parse_expr('a-b'))
<quosure: global>
~a - b

Здесь sym превращает a - b в имя / символ объекта, следовательно, обратный отсчет идет вокруг a - b, а parse_expr превращает его в выражение, как и ожидалось.

person acylam    schedule 03.05.2018

Чтобы дополнить предыдущий ответ, обратите внимание, что ex5 и ex6 на самом деле не идентичны.

a <- 5
b <- 3
eval_tidy(ex6)
# [1] 2
eval_tidy(ex5)
# Error in eval_tidy(ex5) : object 'a - b' not found
`a - b` <- pi
eval_tidy(ex5)
# [1] 3.141593
person Weihuang Wong    schedule 03.05.2018