FAQ
Hi Gophers,

I've created a Gist of 4 different types of For statements, because I
noticed some versions of the for loop allow the block to begin on the next
line, while others do not. After reading the spec, I don't see that
distinction called out, so I'm wondering if this is a
bug. http://golang.org/ref/spec#For_statements

I tested on 1.2.1 and also latest TIP of the default branch at time of this
writing and Go Playground also behaves the same.

https://gist.github.com/vaskoz/10546740

also providing same code in playground for convenience:

http://play.golang.org/p/v5FSCWZZPC

IMPORTANT: DO NOT gofmt (either via command line or playground) the code,
as it actually changes the code in "CForLoopNoPrePost", which I also would
consider a bad thing as it's changing the kind of for statement.

These 4 examples came
from http://www.golangbootcamp.com/book/basic_concepts#sec-for-loop

Many thanks all you helpful and responsive Gophers,
Vasko Zdravevski.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Jan Mercl at Apr 12, 2014 at 5:54 pm
    On Sat, Apr 12, 2014 at 7:34 PM, Vasko Zdravevski wrote:

    I'm not sure where a problem should be, but there's no one. The formal
    grammar doesn't care about newline chars. The tokenizer, however, is
    specified to inject semicolons (semicolon tokens) in certain places:
    http://golang.org/ref/spec#Semicolons.

    In short: Everything in your examples code is WAI - in accordance with
    the specs.

    -j

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
    For more options, visit https://groups.google.com/d/optout.
  • Vasko Zdravevski at Apr 12, 2014 at 6:13 pm
    "Effective Go" says explicitly that blocks should open on the same
    line: http://golang.org/doc/effective_go.html#semicolons

    One consequence of the semicolon insertion rules is that you cannot put the
    opening brace of a control structure (if, for, switch, or select) on the
    next line. If you do, a semicolon will be inserted before the brace, which
    could cause unwanted effects.

    Also, I still think the fact that gofmt actually changes the code rather
    than formatting it from 1 type of for statement to another, especially when
    those two statement obviously behave differently is confusing.

    Thanks,
    Vasko.
    On Saturday, April 12, 2014 11:53:49 AM UTC-6, Jan Mercl wrote:

    On Sat, Apr 12, 2014 at 7:34 PM, Vasko Zdravevski wrote:

    I'm not sure where a problem should be, but there's no one. The formal
    grammar doesn't care about newline chars. The tokenizer, however, is
    specified to inject semicolons (semicolon tokens) in certain places:
    http://golang.org/ref/spec#Semicolons.

    In short: Everything in your examples code is WAI - in accordance with
    the specs.

    -j
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
    For more options, visit https://groups.google.com/d/optout.
  • Jan Mercl at Apr 12, 2014 at 6:47 pm

    On Sat, Apr 12, 2014 at 8:13 PM, Vasko Zdravevski wrote:
    "Effective Go" says explicitly that blocks should open on the same line:
    http://golang.org/doc/effective_go.html#semicolons
    One consequence of the semicolon insertion rules is that you cannot put
    the opening brace of a control structure (if, for, switch, or select) on the
    next line. If you do, a semicolon will be inserted before the brace, which
    could cause unwanted effects.

    Also, I still think the fact that gofmt actually changes the code rather
    than formatting it from 1 type of for statement to another, especially when
    those two statement obviously behave differently is confusing.
    I've never really read Effective Go, only skimmed through it. However,
    the quoted part is 1) not part of the specs, 2) correct only
    partially.

    The particular example in Effective Go is correct:

             if i < f() // wrong!
             { // wrong!
                     g()
             }

    This case is covered by the specs saying a semicolon is injected after
    a ')' being a last non comment token before the line terminating new
    line. However, the 'for' keyword is not amongst the specified
    injection triggering keywords ("break, continue, fallthrough, or
    return"), so

             for
             {
             }

    is, for example, valid Go and Effective Go is a slightly incorrect wrt
    the language specification. Would you mind filling an issue about
    this? https://code.google.com/p/go/issues/list

    -j

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
    For more options, visit https://groups.google.com/d/optout.
  • Vasko Zdravevski at Apr 12, 2014 at 6:57 pm
    I'd be happy to write that up as an issue, but I'm still not clear on 2
    things.

    1. In the spec for for statement, there are 3 possible for
    statements http://golang.org/ref/spec#For_statements - Condition,
    ForClause, and RangeClause.

    This ForClause won't let me move to the newline
    for i := 0; i < 10; i++ {
         sum += i
       }

    but this is still a ForClause type
    for ; sum < 1000;
       {
         sum += sum
       }

    but does allow me to start a block on the next line. I'm not sure, but this
    doesn't seem to have to do with semicolons, IMHO. If you could explain
    this, I'd be very grateful.

    While the Condition type of for statement doesn't allow you to start a
    block on the next line.

    2. gofmt in my example, converts "CForLoopNoPrePost" from a ForClause type
    into a Condition type For statement. Shouldn't this be a bug as well?

    Thanks for taking the time to help me understand this,
    Vasko.
    On Saturday, April 12, 2014 12:46:34 PM UTC-6, Jan Mercl wrote:
    On Sat, Apr 12, 2014 at 8:13 PM, Vasko Zdravevski wrote:
    "Effective Go" says explicitly that blocks should open on the same line:
    http://golang.org/doc/effective_go.html#semicolons
    One consequence of the semicolon insertion rules is that you cannot put
    the opening brace of a control structure (if, for, switch, or select)
    on the
    next line. If you do, a semicolon will be inserted before the brace,
    which
    could cause unwanted effects.

    Also, I still think the fact that gofmt actually changes the code rather
    than formatting it from 1 type of for statement to another, especially when
    those two statement obviously behave differently is confusing.
    I've never really read Effective Go, only skimmed through it. However,
    the quoted part is 1) not part of the specs, 2) correct only
    partially.

    The particular example in Effective Go is correct:

    if i < f() // wrong!
    { // wrong!
    g()
    }

    This case is covered by the specs saying a semicolon is injected after
    a ')' being a last non comment token before the line terminating new
    line. However, the 'for' keyword is not amongst the specified
    injection triggering keywords ("break, continue, fallthrough, or
    return"), so

    for
    {
    }

    is, for example, valid Go and Effective Go is a slightly incorrect wrt
    the language specification. Would you mind filling an issue about
    this? https://code.google.com/p/go/issues/list

    -j
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
    For more options, visit https://groups.google.com/d/optout.
  • Jan Mercl at Apr 12, 2014 at 7:33 pm

    On Sat, Apr 12, 2014 at 8:57 PM, Vasko Zdravevski wrote:
    I'd be happy to write that up as an issue, but I'm still not clear on 2
    things.

    1. In the spec for for statement, there are 3 possible for statements
    http://golang.org/ref/spec#For_statements - Condition, ForClause, and
    RangeClause.

    This ForClause won't let me move to the newline
    for i := 0; i < 10; i++ {
    sum += i
    }

    but this is still a ForClause type
    for ; sum < 1000;
    {
    sum += sum
    }

    but does allow me to start a block on the next line. I'm not sure, but this
    doesn't seem to have to do with semicolons, IMHO. If you could explain this,
    I'd be very grateful.
    Explanation attempt: Semicolon tokens _are_ part of the formal
    grammar. If the semicolon appears where the grammar demands it - ok,
    regardless if injected by the tokenizer or present explicitly ("hard"
    coded by the programmer). If the semicolon doesn't appear where
    required then it's _always_ a syntax error. If the tokenizer is not
    specified to inject a semicolon in a particular case then the lack of
    a semicolon is (still) an error.
    While the Condition type of for statement doesn't allow you to start a block
    on the next line.

    2. gofmt in my example, converts "CForLoopNoPrePost" from a ForClause type
    into a Condition type For statement. Shouldn't this be a bug as well?
    gofmt is never mentioned by the specs. IOW, it's not actually relevant
    to this discussion above the fact that most of Go programmer are so
    used to gofmt'ed code that non gofmt'd one, even when valid, seems to
    us as strange or intuitively even, although sometimes wrongly, as
    invalid.

    -j

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Apr 12, 2014 at 8:45 pm

    On Sat, Apr 12, 2014 at 11:57 AM, Vasko Zdravevski wrote:
    I'd be happy to write that up as an issue, but I'm still not clear on 2
    things.

    1. In the spec for for statement, there are 3 possible for statements
    http://golang.org/ref/spec#For_statements - Condition, ForClause, and
    RangeClause.

    This ForClause won't let me move to the newline
    for i := 0; i < 10; i++ {
    sum += i
    }
    If you write

         for i := 0; i < 10; i++
         {

    then by the semicolon insertion rule
    (http://golang.org/ref/spec#Semicolons) a semicolon will be inserted
    after the i++, giving you

         for i := 0; i < 10; i++;
         {

    which is a syntax error.

    but this is still a ForClause type
    for ; sum < 1000;
    {
    sum += sum
    }

    but does allow me to start a block on the next line. I'm not sure, but this
    doesn't seem to have to do with semicolons, IMHO. If you could explain this,
    I'd be very grateful.

    When you write

         for ; sum < 1000;
         {

    the semicolon insertion rule is not triggered, so no semicolon is
    inserted. The result is a valid for statement with an omitted
    post-statement.

    2. gofmt in my example, converts "CForLoopNoPrePost" from a ForClause type
    into a Condition type For statement. Shouldn't this be a bug as well?
    Your CForLoopNoPrePost omits the init-statement and the
    post-statement, so it is exactly identical to a for loop that only has
    a condition.

    Ian

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
    For more options, visit https://groups.google.com/d/optout.
  • Go-worm at Apr 13, 2014 at 5:40 pm
    Here's a way to think about it. Given that Go uses semicolons behind the
    scenes, think in terms of its needing to 'know' where and where *not* to
    put a semicolon to parse.

    *1.* This is valid because Go doesn't insert a semicolon after a *for*.

    func
    test1() {
    for
    i := 0
    i < 10
    i++ {
    fmt.Println(i)
    }
    }

    *2.* Adding your own semicolons is also valid (but unconventional). Notice
    that if test2() were on its own line, it wouldn't work, because Go normally
    inserts a semicolon for lines that end in yourfunction() calls behind the
    scenes.

    func
    test2() {
    for
    i := 0;
    i < 10;
    i++ {
    fmt.Println(
    i); // notice that it knows not to add a ; after ( above
    };
    };

    *3.* Also valid because you added your own semicolons.

    func test3() { for i := 0; i < 10; i++ { fmt.Println(i); }; };


    *4.* Notice there are no semicolons for this compared to #2 but it's valid.
    When it sees a line like i := 0 on its own, it thinks to normally insert a
    semicolon. So it's added either way:

    func test4() {
    for
        i := 0
        i < 10
        i++ {
           fmt.Println(i)
        }
    }

    *5.* Also valid:

    func test5() {
    i := 0
    for
        ;
        i < 10
        {
           fmt.Println(i)
           i++
        }
    }

    http://play.golang.org/p/E7hTE4V7AN

    It's easiest to follow the conventions. If, however, you have a for line
    that's hard on the eyes, then separate lines can help in
    thinking/readability (like in example #4). This could also confuse people
    looking quickly, into wondering why there's seemingly a lack of a left
    bracket after for. It's your call.


    On Saturday, April 12, 2014 12:34:51 PM UTC-5, Vasko Zdravevski wrote:

    Hi Gophers,

    I've created a Gist of 4 different types of For statements, because I
    noticed some versions of the for loop allow the block to begin on the next
    line, while others do not. After reading the spec, I don't see that
    distinction called out, so I'm wondering if this is a bug.
    http://golang.org/ref/spec#For_statements

    I tested on 1.2.1 and also latest TIP of the default branch at time of
    this writing and Go Playground also behaves the same.

    https://gist.github.com/vaskoz/10546740

    also providing same code in playground for convenience:

    http://play.golang.org/p/v5FSCWZZPC

    IMPORTANT: DO NOT gofmt (either via command line or playground) the code,
    as it actually changes the code in "CForLoopNoPrePost", which I also would
    consider a bad thing as it's changing the kind of for statement.

    These 4 examples came from
    http://www.golangbootcamp.com/book/basic_concepts#sec-for-loop

    Many thanks all you helpful and responsive Gophers,
    Vasko Zdravevski.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedApr 12, '14 at 5:34p
activeApr 13, '14 at 5:40p
posts8
users4
websitegolang.org

People

Translate

site design / logo © 2023 Grokbase