【问题标题】:Capture argument expression used for S3 dispatch捕获用于 S3 调度的参数表达式
【发布时间】:2023-03-27 22:40:01
【问题描述】:

我发现 rlang 和 base 之间的行为出现了意想不到的分歧。正如这句话所证明的那样,显然存在差异。这是从 0.4.1 开始的,但类似的语言仍在 0.4.2 中,现在指的是enquo。

就基函数而言,enexpr(arg) 对应于 base::substitute(arg)(尽管该函数还具有复杂的替换语义)

  1. 任何人都可以使用substitute() 具有的 rlang 函数来匹配行为吗?
  2. 有没有很好的解释为什么enexpr() 不起作用?我猜是因为它与 S3 方法调度有关。
  3. 我对如何使用 rlang 实现这一点特别感兴趣,我已经可以仅使用 base 实现我想要的行为。

我的示例是无稽之谈,但它强调的是我无法捕获作为通用 S3 函数的第一个参数传入的表达式(在本例中为单个符号 df)。

library(rlang)
f <- function(obj) {
  enexpr(obj)
}
print(f(print("hello")))
#> print("hello")
# behavior matches expectations

df <- data.frame(a = 1:5, b = letters[1:5])
class(df) <- c("custom", class(df))
`[.custom` <- function(x, i) {
call2(expr(`[`), enexpr(x), i)
}
df[4]
#> list(a = 1:5, b = 1:5)[4]
sloop::s3_dispatch(df[4])
#> => [.custom
#>  * [.data.frame
#>    [.default
#>  * [ (internal)
# It's dispatching as expected, but I don't get
# `df[4]` back as a call. 

df <- data.frame(a = 1:5, b = letters[1:5])
class(df) <- c("custom", class(df))
`[.custom` <- function(x, i) {
  call2(expr(`[`),substitute(x), i)
}
df[4]
#> df[4]
# substitute works

packageVersion("rlang")
#> [1] '0.4.2'
# Created on 2019-12-05 by the reprex package (v0.3.0)

【问题讨论】:

  • rlang 的一位作者评论了similar question's answer:他们更喜欢rlang 内部的一致性,而不是完全模仿base。
  • 感谢亚历克西斯的评论。这是有道理的,只是在包中找不到记录不一致的地方。

标签: r rlang tidyeval


【解决方案1】:

这是rlang 的documented issue,未来版本中可能会添加支持。

当前的解决方法是在调度时引入另一个级别的引用:

`[` <- function(x, i) {
  ex <- eval_tidy( enquo(x) )
  UseMethod('[', ex)
}

`[.custom` <- function(x, i)
  call2(expr(`[`), enexpr(x), i)

df[4]
# df[4]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-20
    • 2012-02-21
    • 1970-01-01
    • 2019-10-08
    • 2017-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多