rlang 包中的 sym() 和 parse_expr() 有什么区别?
What is the difference between sym() and parse_expr() in the rlang package?
使用rlang包,想知道sym()
和parse_expr()
有什么区别。例如考虑以下表达式:
ex1 = sym('a')
ex2 = parse_expr('a')
他们俩return
a
identical(ex1, ex2)
[1] TRUE
假设现在我需要一个quosure:
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'))
显然它们是相同的 return:
<quosure>
expr: ^a - b
env: global
还有,
identical(ex5, ex6)
[1] FALSE
所以,我的问题是,sym()
和 parse_expr()
之间有什么区别?
一个人能做什么而另一个人不能?为什么 ex5
明显类似于 ex6
,但 identical(ex5, ex6)
return 是假的?
参考我对此的回答:
符号是指代 R 对象的一种方式,基本上是对象的“名称”。所以 sym
类似于基础 R 中的 as.name
。另一方面,parse_expr
将一些文本转换为 R 表达式。这类似于基础 R 中的 parse
。
表达式可以是任何 R 代码,而不仅仅是引用 R 对象的代码。所以你可以解析引用R对象的代码,但是如果代码引用的对象不存在,你不能将一些随机代码变成sym
。
通常,当您的字符串引用一个对象时,您将使用 sym
(尽管 parse_expr
也可以),并在您尝试解析任何其他对象时使用 parse_expr
用于进一步评估的 R 代码。
对于您的第一个示例,a
可以是引用对象的名称和表达式,因此将其转换为 sym
或 parse_expr
实际上意味着相同事物。事实上,R 会在可能的情况下将表达式隐式转换为 sym
,如第一个示例所示。
然而,对于您的最后一个示例,a - b
实际上是一个表达式(除非您有一个奇怪地命名为 a - b
的 R 对象)。通过打印以下内容,您将看到使用 sym
与 parse_expr
的 R 代码 是一个表达式,而不是 R 对象 会产生两个不同的结果:
> quo(!!sym('a - b'))
<quosure: global>
~`a - b`
> quo(!!parse_expr('a-b'))
<quosure: global>
~a - b
在这里,sym
将 a - b
变成一个对象的 name/symbol,因此在 a - b
周围打勾, while parse_expr
将其转换为预期的表达式。
为了补充前面的答案,请注意 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
使用rlang包,想知道sym()
和parse_expr()
有什么区别。例如考虑以下表达式:
ex1 = sym('a')
ex2 = parse_expr('a')
他们俩return
a
identical(ex1, ex2)
[1] TRUE
假设现在我需要一个quosure:
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'))
显然它们是相同的 return:
<quosure>
expr: ^a - b
env: global
还有,
identical(ex5, ex6)
[1] FALSE
所以,我的问题是,sym()
和 parse_expr()
之间有什么区别?
一个人能做什么而另一个人不能?为什么 ex5
明显类似于 ex6
,但 identical(ex5, ex6)
return 是假的?
参考我对此的回答
符号是指代 R 对象的一种方式,基本上是对象的“名称”。所以 sym
类似于基础 R 中的 as.name
。另一方面,parse_expr
将一些文本转换为 R 表达式。这类似于基础 R 中的 parse
。
表达式可以是任何 R 代码,而不仅仅是引用 R 对象的代码。所以你可以解析引用R对象的代码,但是如果代码引用的对象不存在,你不能将一些随机代码变成sym
。
通常,当您的字符串引用一个对象时,您将使用 sym
(尽管 parse_expr
也可以),并在您尝试解析任何其他对象时使用 parse_expr
用于进一步评估的 R 代码。
对于您的第一个示例,a
可以是引用对象的名称和表达式,因此将其转换为 sym
或 parse_expr
实际上意味着相同事物。事实上,R 会在可能的情况下将表达式隐式转换为 sym
,如第一个示例所示。
然而,对于您的最后一个示例,a - b
实际上是一个表达式(除非您有一个奇怪地命名为 a - b
的 R 对象)。通过打印以下内容,您将看到使用 sym
与 parse_expr
的 R 代码 是一个表达式,而不是 R 对象 会产生两个不同的结果:
> quo(!!sym('a - b'))
<quosure: global>
~`a - b`
> quo(!!parse_expr('a-b'))
<quosure: global>
~a - b
在这里,sym
将 a - b
变成一个对象的 name/symbol,因此在 a - b
周围打勾, while parse_expr
将其转换为预期的表达式。
为了补充前面的答案,请注意 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