【问题标题】:What is the difference between sym() and parse_expr() in the rlang package?rlang 包中的 sym() 和 parse_expr() 有什么区别?
【发布时间】:2018-05-03 15:34:21
【问题描述】:

使用rlang包,我想知道sym()parse_expr()有什么区别。例如,考虑以下表达式:

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

他们都回来了

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'))

显然它们是相同的,因为两者都返回:

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

然而,

identical(ex5, ex6)
[1] FALSE

那么,我的问题是,sym()parse_expr() 之间有什么区别? 一个做什么而另一个不能做什么?为什么ex5 明显类似于ex6,但identical(ex5, ex6) 返回FALSE?

【问题讨论】:

    标签: r string evaluation rlang


    【解决方案1】:

    参考我对此question的回答:

    符号是引用 R 对象的一种方式,基本上是对象的“名称”。所以sym 类似于基础 R 中的as.name。另一方面,parse_expr 将一些文本转换为 R 表达式。这类似于基础 R 中的parse

    表达式可以是任何 R 代码,而不仅仅是引用 R 对象的代码。所以你可以解析引用R对象的代码,但是如果代码引用的对象不存在,你就不能把一些随机代码变成sym

    一般来说,当您的字符串引用一个对象时,您将使用sym(尽管parse_expr 也可以使用),而当您尝试解析任何其他R 代码以进行进一步评估时,您将使用parse_expr

    对于您的第一个示例,a 既可以是引用对象的名称也可以是表达式,因此将其转换为 symparse_expr 实际上意味着相同的事情。事实上,R 会尽可能将表达式隐式转换为 sym,如您的第一个示例所示。

    但是,对于您的最后一个示例,a - b 确实是一个表达式(除非您有一个奇怪地命名为 a - b 的 R 对象)。通过打印以下内容,您将看到将symparse_expr 用于R 代码这是一个表达式,而不是一个R 对象会产生两种不同的结果:

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

    这里,syma - b 转换为对象的名称/符号,因此a - b 周围的后面打勾,而parse_expr 按预期将其转换为表达式。

    【讨论】:

      【解决方案2】:

      要补充前面的答案,请注意 ex5ex6 实际上并不相同。

      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
      

      【讨论】:

        猜你喜欢
        • 2019-09-16
        • 1970-01-01
        • 1970-01-01
        • 2018-10-01
        • 2018-08-18
        • 2019-01-24
        • 2017-12-05
        • 2011-07-05
        • 2021-03-23
        相关资源
        最近更新 更多