Grammar of if statements

64 views
Skip to first unread message

Jeffrey

unread,
Dec 4, 2009, 6:53:50 PM12/4/09
to golang-nuts
From the Go Programming Language Specification:

IfStmt = "if" [SimpleStmt ";"] [Expression] Block ["else" Statement].

What stood out to me was the Statement after the "else". "Statement"
is probably there to allow one to say "else if" directly without
needing to say "else { if ... }". But it also allows any statement to
follow an else. The following compiles and runs just fine with 8g+8l:

func compare(left, right int) iint {
var result int;
if (left > right) {
result = 1;
} else if (left < right) {
result = -1;
} else // <--- no open brace required
result = 0;
// <--- no closing brace required
return result;
}

There doesn't appear to be any ambiguity in associating an else with
an if with the current grammar, but it seems rather inconsistent. Was
this by design? Or, was the real intent to say:

IfStmt = "if" [SimpleStmt ";"] [Expression] Block ["else" (IfStmt |
Block)].

- Jeffrey

Ken Thompson

unread,
Dec 4, 2009, 8:29:05 PM12/4/09
to Jeffrey, golang-nuts
there is no error in the grammar.
the else-side expects a "statement",
and not a "block".

i know this is a raging controversy,
but it is shorter and looks better.

the then-side takes a "block" for two
reasons. 1) without () around the condition,
the grammar would be ambiguous. 2) it resolves
the dangling else ambiguity.

i can tell you that the 5 of us have split
opinions on this subject, but i believe
that brevity, freedom of choice, and
screaming and shouting won the day.

ken

Jeffrey

unread,
Dec 4, 2009, 9:43:15 PM12/4/09
to golang-nuts
On Dec 4, 5:29 pm, Ken Thompson <k...@google.com> wrote:

> i know this is a raging controversy,
> but it is shorter and looks better.

Fair enough. It's certainly consistent with the rest of the language,
in that grammatically unnecessary punctuation is either optional
(e.g., semicolons after global declarations) or disallowed (semicolons
after "package main", or no colons in variable declarations as in
Pascal) but rarely if ever mandatory. It does give the code an
overall clean, uncluttered look.

Also, consistent with the language, gofmt strives to strip away
unnecessary punctuation, like parentheses around if conditions.

But curiously, according to gofmt, the else "looks better" with the
braces than without.

Thanks for the response.

- Jeffrey

baldmountain

unread,
Dec 4, 2009, 11:44:28 PM12/4/09
to golang-nuts
On Dec 4, 8:29 pm, Ken Thompson <k...@google.com> wrote:
> i can tell you that the 5 of us have split
> opinions on this subject, but i believe
> that brevity, freedom of choice, and
> screaming and shouting won the day.

Count me on the block side. Not because of any insight into language
design, but because of safety. It is WAY too easy to start with:

if (left > right) {
result = 1;
} else if (left < right) {
result = -1;
} else // <--- no open brace required
result = 0;

and change it to:

if (left > right) {
result = 1;
} else if (left < right) {
result = -1;
} else // <--- no open brace required
result = 0;
return result;

and expect the return result statement to be executed ONLY for the
final else rather than every time.


geoff

Russ Cox

unread,
Dec 4, 2009, 11:49:51 PM12/4/09
to baldmountain, golang-nuts
> Count me on the block side. Not because of any insight into language
> design, but because of safety. It is WAY too easy to start with:

Thanks for your input, but reopening this discussion
is only going to cause a lot of mail without changing
the situation, which is: the grammar allows else without
braces, but gofmt adds them anyway.

Like all things gofmt, the point is to agree to have a
standard, not to agree on what the standard is.

Russ

Ben Tilly

unread,
Dec 5, 2009, 1:08:29 AM12/5/09
to baldmountain, golang-nuts
If you expect the else to be a block, and don't add a special case to
the grammar, you would need to write your example as:

if left > right {
result = 1;
}
else {
if left < right {
result = -1;
}
else {
result = 0;
}
}

As much as I would never leave the {} off the final else, I can
certainly understand the decision that was made.

Cheers,
Ben

baldmountain

unread,
Dec 5, 2009, 9:40:08 AM12/5/09
to golang-nuts
Sorry Russ, I can't help myself. :)

On Dec 5, 1:08 am, Ben Tilly <bti...@gmail.com> wrote:
> If you expect the else to be a block, and don't add a special case to
> the grammar, you would need to write your example as:
>
>   if left > right {
>       result = 1;
>   }
>   else {
>       if left < right {
>           result = -1;
>       }
>       else {
>           result = 0;
>       }
>   }
>
> As much as I would never leave the {} off the final else, I can
> certainly understand the decision that was made.


Another possibility is to add elif

if left > right {
result = 1;
}
elif left < right {
result = -1;
}
else {
result = 0;
}

where if, elif and else all take blocks. But then I'd write this as a
switch:

switch {
case: left > right
result = 1;
case: left < right {
result = -1;
default:
result = 0;
}

I should say that I'm commenting from experience rather than language
design knowledge. Go has some different ideas that cause you to
rethink the way you program. This is one of those. When you need to
decide between 2 or 3 options you reach for an 'if else' statement.
The switch statement is SO general purpose that you don't really need
'if else' at all other than being syntactic sugar for:

switch {
case: left > right
result = 1;
case: left < right {
result = -1;
default:
result = 0;
}

I've written some code where I use switch to choose between 2 options
and the second option is default:.


geoff

P.S. OK Russ, I'll shutup now. :)
Reply all
Reply to author
Forward
0 new messages