Indeed, an example in the documentation about this feature would be helpful, may
be the one Hugh used. If an explanation is deemed appropriate, I would suggest
including something along the lines of the following
(after the second paragraph of the Details section for if/while/etc.).
==============
In these constructs the opening braces, if any, are part of the expression to be
evaluated, not syntax delimiters.
In particular, the expression does not necessarily end with the closing brace.
For example, '{2} + 3' and '2 + 3' are equivalent expressions,
so the first command below gives 0, not 3.
> if(TRUE) 0 else {2} + 3
[1] 0> if(TRUE) 0 else 2 + 3
[1] 0
===============
In practice, this confusion appears mainly in the 'else' part of
'if' constructs. But it is not limited there. For example, this defines
a function with body x^2 + 1, for the same reasons, although one might expect an
error.
> f <- function(x){x^2} + 1
> f(2)
[1] 5> as.character(body(f))
[1] "+" "{\n x^2\n}" "1"
>
Georgi Boshnakov
------------------------------
Message: 5
Date: Sat, 17 Aug 2019 02:36:39 +1000
From: Hugh Parsonage <hugh.parsonage at gmail.com>
To: R-devel <r-devel at r-project.org>
Subject: [Rd] Documenting else's greed
Message-ID:
<CAJmOi+O-3gUjdEmFJQhTfNxwUzQ86snSti_6yt26zJRDjgX7Ug at
mail.gmail.com>
Content-Type: text/plain; charset="utf-8"
I was initially pretty shocked by the result in this question:
https://stackoverflow.com/questions/57527434/when-do-i-need-parentheses-around-an-if-statement-to-control-the-sequence-of-a-f
Briefly, the following returns 0, not 3 as might be expected:
if (TRUE) {
0
} else {
2
} + 3> f
function(x){x^2} + 1> body(f)
{
x^2
} + 1> f(2)
[1] 5
At first I thought it the question was simply one of syntax
precedence, but I believe the result is too surprising to not warrant
note in the documentation of Control. I believe the documentation
should highlight that the `alt.expr` is demarcated by a semicolon or
newline and the end of a *statement*, not a closing brace per se.
Perhaps in the paragraph starting 'Note that it is a common mistake to
forget to put braces...' it should end with. "Note too that it is the
end of a *statement*, not a closing brace per se, that determines
where `alt.expr` ends. Thus if (cond) {0} else {2} + 2 means if (cond)
{0} else {2 + 2} not {if (cond) {0} else {2}} + 2."
------------------------------
Message: 6
Date: Fri, 16 Aug 2019 16:31:15 -0400
From: Duncan Murdoch <murdoch.duncan at gmail.com>
To: Hugh Parsonage <hugh.parsonage at gmail.com>, R-devel
<r-devel at r-project.org>
Subject: Re: [Rd] Documenting else's greed
Message-ID: <d0ead42a-24da-8bb6-b924-3f799efa04ac at gmail.com>
Content-Type: text/plain; charset="utf-8"; Format="flowed"
On 16/08/2019 12:36 p.m., Hugh Parsonage wrote:> I was initially pretty shocked by the result in this question:
>
https://stackoverflow.com/questions/57527434/when-do-i-need-parentheses-around-an-if-statement-to-control-the-sequence-of-a-f
>
> Briefly, the following returns 0, not 3 as might be expected:
>
> if (TRUE) {
> 0
> } else {
> 2
> } + 3
>
> At first I thought it the question was simply one of syntax
> precedence, but I believe the result is too surprising to not warrant
> note in the documentation of Control. I believe the documentation
> should highlight that the `alt.expr` is demarcated by a semicolon or
> newline and the end of a *statement*, not a closing brace per se.
>
> Perhaps in the paragraph starting 'Note that it is a common mistake to
> forget to put braces...' it should end with. "Note too that it is
the
> end of a *statement*, not a closing brace per se, that determines
> where `alt.expr` ends. Thus if (cond) {0} else {2} + 2 means if (cond)
> {0} else {2 + 2} not {if (cond) {0} else {2}} + 2."
I agree this is surprising, and should perhaps be pointed out in the
docs, but I don't think your suggestion is quite right. { 2 } + 3 is a
legal expression. It doesn't have to be the end of a statement that
limits the alt.expr, e.g. this could be one big statement:
{ if (TRUE) {
0
} else {
2
} + 3 }
What ends alt.expr is a token that isn't collected as part of alt.expr,
not just a semicolon (which separates statements) or a newline. I don't
know how many of those there are, but the list would include at least
semicolon, newline, }, ), ], and maybe others.
Duncan Murdoch