tidyeval icon indicating copy to clipboard operation
tidyeval copied to clipboard

Consider evocative aliases

Open hadley opened this issue 7 years ago • 10 comments

@jimhester suggested:

  • tidy_capture() and tidy_capture_dots() for enquo() and enquos()
  • tidy_build() for expr()
  • tidy_eval() for eval_tidy()

But we should consider all functions used in the book before providing any new aliases

hadley avatar Aug 28 '18 13:08 hadley

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 thetidy_ 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.

lionel- avatar Aug 28 '18 15:08 lionel-

  • I like how build() suggests it's building a more complex expression. If we go for build() then we'll have to embrace the quote() / build() dichotomy as in lisp.

  • Instead of capture, could be auto_quote() and auto_quote_list().

lionel- avatar Aug 28 '18 15:08 lionel-

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.

batpigandme avatar Aug 28 '18 16:08 batpigandme

delay_action(arg)    # enquo()
delay_variable(arg)  # ensym()

as_name(delay_variable(arg))
as_label(delay_action(arg))

lionel- avatar Dec 29 '18 11:12 lionel-

action <- delay_action(arg)
action <- expand(mean(!!action, na.rm = TRUE))

lionel- avatar Dec 29 '18 11:12 lionel-

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

hadley avatar Dec 31 '18 14:12 hadley

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.

lionel- avatar Jan 02 '19 10:01 lionel-

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.

hadley avatar Jan 02 '19 14:01 hadley

Funnily enough, I was just discussing this with Andy Stefik...

gvwilson avatar Jan 02 '19 14:01 gvwilson

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

lionel- avatar Oct 31 '19 17:10 lionel-