[Rd] Printing of anonymous functions in calls is sub-optimal

Duncan Murdoch murdoch.duncan at gmail.com
Sun Feb 17 00:29:58 CET 2013

On 13-02-16 10:22 AM, Hadley Wickham wrote:
>> This is a little tricky for the deparser.  It sees a call to a function
>> which was determined by an expression.  Sometimes you want parens, sometimes
>> you don't.  For example, if getfun(y) returns a function, it's clearer to
>> display a call as getfun(y)(x) than (getfun(y))(x).
>> I'll see if I can work out which kinds of expressions need to be
>> parenthesized and implement it in the deparser.
> I suspect it's only when you have a function in the quoted call, not a symbol:
> # Don't add parens
> q1 <- quote(g(f)(x))
> is.symbol(q1[[1]])
> # Add parents
> q2 <- substitute(f(x), list(f = function(x) {x + 1}))
> is.function(q2[[1]])
> Thanks for thinking about it!

It's in place now.  There are two kinds of cases it handles:

Unevaluated expressions are the hardest.  For those, parens are used 
when the function is an infix operator other than ::, :::, $, [ or [[.
They're also used for special syntax, like if, while, etc.

For evaluated things, only your example (a closure object) get parens.

I'm sure you can construct things that deparse improperly, but it does a 
better job now.  For example, from the new test script:

 > ## Anonymous function calls were not deparsed properly
 > substitute(f(x), list(f = function(x) x + 1))
(function (x)
x + 1)(x)
 > substitute(f(x), list(f = quote(function(x) x + 1)))
(function(x) x + 1)(x)
 > substitute(f(x), list(f = quote(f+g)))
(f + g)(x)
 > substitute(f(x), list(f = quote(base::mean)))
 > substitute(f(x), list(f = quote(a[n])))
 > substitute(f(x), list(f = quote(g(y))))
 > ## The first three need parens, the last three don't.

This is in R-devel and R-patched.

Duncan Murdoch

More information about the R-devel mailing list