Consider evocative aliases
@jimhester suggested:
-
tidy_capture()andtidy_capture_dots()forenquo()andenquos() -
tidy_build()forexpr() -
tidy_eval()foreval_tidy()
But we should consider all functions used in the book before providing any new aliases
That's similar to the naming scheme we had in earlier versions of rlang. Some thoughts:
-
Probably not worth renaming
eval_tidy()which is a very specialised function. -
We should probably steer away from the
tidy_prefix. If the goal is autocompletion you'll find many disparate functions in that namespace. -
I worry that it's too late to change the names and having two sets of names + friendlyeval is going to make things more complicated.
-
I like how
build()suggests it's building a more complex expression. If we go forbuild()then we'll have to embrace thequote()/build()dichotomy as in lisp. -
Instead of capture, could be
auto_quote()andauto_quote_list().
FWIW expr() is more meaningful at a glance than build() is to me at least. build_expr() would kind of capture both, though I don't know that it's a great function name. There are also some mental namespace collisions with build() in terms of R/RStudio commands (surmountable obstacles for sure), but just putting that out there… Again, not a function name, but I somehow think of it more as constructing than building (which 🙄, yeah, they're basically synonyms).
Also possible that my mental model is just totally wrong, since you blew my mind yesterday with the enquo() expr() thing.
delay_action(arg) # enquo()
delay_variable(arg) # ensym()
as_name(delay_variable(arg))
as_label(delay_action(arg))
action <- delay_action(arg)
action <- expand(mean(!!action, na.rm = TRUE))
Why do you prefer delay_ over capture_?
One reason might be to pick an antonym for eval() and delay() + advance() is more evocative than capture() + release()
I was thinking about delay_ and resume(). I'm considering whether explaining NSE in term of delaying of computation may be more intuitive for beginners.
-
Sourcing an R file triggers a series of computation, getting results after results. If a function suspends that process of computation, it gets the blueprint of the computation instead.
-
Why suspend? In order to resume computation with the blueprint in a different context (the user's data).
I think "delaying" instead of "quoting" or "capturing" is more suggestive of why we need to quote. If users understands why, they are more likely to remember what to do the next time around.
The next step is to understand how to change blueprints. It's easy to change results, but to change a blueprint we need !!. That's the surgical operator that allows you to modify a blueprint. When you're dealing with code as text, the surgical operator is %s or { }. When you're dealing with code as blueprint, it's !!.
Finally, what are blueprints made of: variables (symbols) and actions (function calls). Though I'm not entirely happy with delay_action() because that suggests it always returns calls, just like delay_variable() always returns symbols.
I think if we decide to change the names, we need to design some sort of experiment so that we can validate that the new names are actually easier for people to understand. I know that @gvwilson would be very happy to help out with this sort of experiment.
Funnily enough, I was just discussing this with Andy Stefik...
Going with the defusing / booby trap analogy:
expr() -> defuse()
enquo() -> arg_defuse()
defuse() prevents evaluation of your own expression. arg_defuse() prevents evaluation of a function argument.
defuse() seems to go well with blast():
dfs <- list(mtcars[1:2, 1:4], mtcars[3:4, 1:4])
defuse(rbind(!!!dfs))
#> rbind(<data.frame>, <data.frame>)
blast(rbind(!!!dfs))
#> mpg cyl disp hp
#> Mazda RX4 21.0 6 160 110
#> Mazda RX4 Wag 21.0 6 160 110
#> Datsun 710 22.8 4 108 93
#> Hornet 4 Drive 21.4 6 258 110