From murdoch.duncan at gmail.com  Sun Feb 17 00:29:58 2013
From: murdoch.duncan at gmail.com (Duncan Murdoch)
Date: Sat, 16 Feb 2013 18:29:58 -0500
Subject: [Rd] Printing of anonymous functions in calls is sub-optimal
In-Reply-To: <CABdHhvGsqp76OZYLm12R9AvrekY5KnL3tOwPHpSnc0c2=DPyvQ@mail.gmail.com>
References: <CABdHhvEgK1g4gYhmovu_EbvSN185g9LnLAacC5ojWup3_aG07w@mail.gmail.com>
	<511FA362.9060305@gmail.com>
	<CABdHhvGsqp76OZYLm12R9AvrekY5KnL3tOwPHpSnc0c2=DPyvQ@mail.gmail.com>
Message-ID: <51201676.2000208@gmail.com>

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)))
base::mean(x)
 > substitute(f(x), list(f = quote(a[n])))
a[n](x)
 > substitute(f(x), list(f = quote(g(y))))
g(y)(x)
 > ## The first three need parens, the last three don't.
 >

This is in R-devel and R-patched.

Duncan Murdoch



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