From murdoch.duncan at gmail.com  Sun Feb 17 19:54:34 2013
From: murdoch.duncan at gmail.com (Duncan Murdoch)
Date: Sun, 17 Feb 2013 13:54:34 -0500
Subject: [Rd] Printing of anonymous functions in calls is sub-optimal
In-Reply-To: <51201676.2000208@gmail.com>
References: <CABdHhvEgK1g4gYhmovu_EbvSN185g9LnLAacC5ojWup3_aG07w@mail.gmail.com>
	<511FA362.9060305@gmail.com>
	<CABdHhvGsqp76OZYLm12R9AvrekY5KnL3tOwPHpSnc0c2=DPyvQ@mail.gmail.com>
	<51201676.2000208@gmail.com>
Message-ID: <5121276A.30206@gmail.com>

On 13-02-16 6:29 PM, Duncan Murdoch wrote:
> 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.

This broke a number of packages, which depended on the particular text 
of deparsed expressions, so we're going to revert the R-patched fix. 
R-devel (to become 3.0.0) will get it, but not 2.15.3.

Duncan Murdoch



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