r-lib / rlang

Low-level API for programming with R
https://rlang.r-lib.org
Other
508 stars 138 forks source link

Function-style syntax for {{ #1337

Closed kmillar closed 2 years ago

kmillar commented 2 years ago

Please consider adding a function-style alternative syntax for {{. I suggest using the name forward_arg. User code would then look like:

my_mean <- function(data, var) {
  dplyr::summarise(data, mean = mean(forward_arg(var)))
}

The advantages of doing so would be:

It also makes it possible to define a function you can both document and that gives a helpful error message if forward_arg is used in an incorrect context.

#' <documentation of the way forward_arg works in a tidyeval context>
forward_arg <- function(arg) {
  stop("forward_arg() only supported in tidyeval contexts.")
}
lionel- commented 2 years ago

We decided to use operator syntax instead of function-call syntax because forwarding an argument (or injecting an object in general) is not a function call. This is following the lisp tradition where unquoting/injection is one of the rare non-word syntax in the language.

Also we prefer that there is only one way to perform that operation. The UQ() and UQS() variants introduced in rlang 0.1.0 have long been soft-deprecated.

kmillar commented 2 years ago

Thanks for the explanation. I'd like to disagree on a number of points and urge reconsidering the decision to only have one way to perform this operation.

IIUC in lisp, unquoting can be done with either unquote or ,. Adding forward_arg or similar would make rlang closer to what lisp does.

ln lisp it's part of the language itself and the users are generally programmers. Macros and metaprogramming are considered part of learning lisp. In that context you can get away with syntax that isn't so obvious. For rlang you have a number of complications that make it important to be as clear as possible:

In that context it's much more important to make things as clear and readable as possible to people who don't have an in-depth knowledge of how the package works. While {{ would arguably be an elegant syntax for this type of functionality in the core of a programming language used by software engineers, I think that we would be much better served by something more readable here.

Lesser points:

As a somewhat related aside, I don't think that quoting/unquoting is quite the right vocabulary for this functionality in R, but I don't have a better suggestion yet. forward_arg isn't really right as it only describes the case where you're passing the argument directly. insert_arg might be a bit better. I'll let you know if and when I come up with a better word for what {{ does.

Thanks

lionel- commented 2 years ago

IIUC in lisp, unquoting can be done with either unquote or ,. Adding forward_arg or similar would make rlang closer to what lisp does.

I see some evidence of that in racket, a scheme dialect. I don't think this is the norm. In any case I've never seen any other usage than through syntactic signs. It would be harder to read quasiquoting code without special syntax.

The users are primarily data scientists and statisticians, not programmers.

I've only heard positive feedback about {{. So far the syntax seems intuitive for a large group of meta-programmers, including data scientists and statisticians.

Calling {{ 'embrace' makes it easier to describe the syntax, but it doesn't really tie into the functionality at all, so it doesn't help making the code easier to read and understand.

You can also call it "tunnelling" for a more descriptive term. This is orthogonal to the syntactic issue though.

Brevity isn't particularly important here, as {{ isn't likely to be used much in data analysis code.

This is not about brevity but about standing out.

insert_arg might be a bit better. I'll let you know if and when I come up with a better word for what {{ does.

FWIW the adequate term would involve "inject", and then the operator would be competing with (would need to be consistent and meaningful in conjunction with) the name of the existing inject() function. But we are not looking to introduce new syntax to tidyeval and we have decided years ago against function call syntax.