All functions in R are anonymous: they to not need to be bound to a variable. If a function does happen to be bound to one or more variables, there is no way to recover the names those variables from a function object.
Functions in R are written and printed using the syntax
function(x) x + 1
It is not uncommon to see comments from new users that this is a lot to write, especially for very simple functions like this one. It is hard to see that writing is really a significant issue: Any reasonable IDE/editor either already has a shortcut or allows one to be created. The impact on code readability may be another matter. Functional programming expressions in particular, like
lapply(y, function(t) is.null(t) || anyNA(t))
or
Reduce(function(u, v) u + 1 / v, x, right = TRUE)
might be more readable with a more concise notation.
The tidyverse has introduces a formula-based notation. The gsubfun
package uses another formula-based approach. And there are probably others. But these only work within the functions for which they are designed.
An alternative worth exploring is for base R to support a concise syntax in the parser. Ideally such a syntax should be able to express any function, allowing for multiple arguments, default arguments, and ...
, though it would be most useful for simple functions.
Three possibilities we have considered that were mentioned in my useR 2020 keynote are
(x) => x + 1
, (x, y) => x + y
(Javascript; similar to Julia).\(x) x + 1
, \(x, y) x + y
(similar to Haskell; \
simulates \(\lambda\)).@(x) x + 1
, @(x, y) x + y
(Matlab, Octave).All three have been implemented in the R-syntax
subversion branch.
The second and third are the most concise, perhaps too concise. But they require only minimal parser changes.
The first option requires more extensive parser changes. My first attempt was not good, but Andrew Craig modified the R
3.6.3 gram.y
to make (x) => x + 1 work (tweet, Tokyo.R talk, code on GitHub), and I ported his changes to the current parser. These changes do seem to work, but my concern is that they may impose too great a burden on maintaining the parser.
All of these are only syntactic sugar for the longer version using function
. The parsed AST is the same:
> quote((x) => x + 1)
function(x) x + 1
> quote(\(x) x + 1)
function(x) x + 1
> quote(@(x) x + 1)
function(x) x + 1
Parse data and source references do reflect the way the expressions were entered. This is analogous to the way right assignment ->
is handled:
> quote(1 -> x)
x <- 1
Editor support, e.g. in RStudio or ESS, and code formatting tools, e.g. lintr
and styler
would need to be updated for the new surface syntax.