Reputation: 1438
I came across an unexpected divergence of behavior between rlang and base. Differences clearly exist, as evidenced by this quote. This was from 0.4.1, but similar language is still in 0.4.2, now referring to enquo
instead.
In terms of base functions, enexpr(arg) corresponds to base::substitute(arg) (though that function also features complex substitution semantics)
substitute()
has?enexpr()
doesn't work? I am guessing because it is related to S3 method dispatch.My example is nonsense, but what it highlights is I am unable to capture the expression (in this case a single symbol, df
) passed in as the first argument to a generic S3 function.
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)
Upvotes: 2
Views: 90
Reputation: 13691
This is a documented issue for rlang
, and support is likely to be added in future versions.
The current workaround is to introduce another level of quoting at dispatch:
`[` <- function(x, i) {
ex <- eval_tidy( enquo(x) )
UseMethod('[', ex)
}
`[.custom` <- function(x, i)
call2(expr(`[`), enexpr(x), i)
df[4]
# df[4]
Upvotes: 1