FAQ
Hello, Gophers :-)

I'm sure this must have been asked before, but I searched the forums and
the Wiki, and the closest thing I could find to an explanation, was this:

https://code.google.com/p/go-wiki/source/browse/SimultaneousAssignment.wiki?repo=wiki

So I get the part about simultaneous assignment, but that's not really my
question...

What baffles me time and again, is when other statements, separated by
semi-colons, are rolled into if-statements... for example:

     if _, err: = fmt.Sscanf(line, "%f%f", &radius, &θ); err!=nil {
         ....
     }

I understand how it works, or at least I think so ;-)

But I don't understand why anyone would do that?

To me, this is much more legible:

     _, err: = fmt.Sscanf(line, "%f%f", &radius, &θ)

     if err!=nil {
         ....
     }

I get that the first statement in this example is related to the
if-statement, but it isn't *part* of the if-statement, and it makes the
if-statement really hard to read, because the first statement isn't part of
the *condition*, which is what I expect to see after the word *if*.

Why do you see this sort of thing so often in Go programs?

Does it serve a purpose, other than garbling the code (and complicating
change management in source control) in an attempt to communicate the fact
that the if-statement is *dependent* on the other statement?

I'm hoping there's some subtle *functional* difference that I've missed,
because this convention leads to otherwise unjustified tangles in the code.

It brings to mind the "backwards if-statements" in Ruby, where if
if-statement and *pre*-condition is placed *after* the conditional
statement - to me, this sort of thing is *clever* but not *simple*, and
from what I've seen so far, the Go language (and community) always stays
away from *clever* whenever it is possible to keep things *simple*.

Only a few days in, but I love the simplicity of the Go language thus far
:-)

But this one baffles me.

Explain, please? :-)

thanks!

--
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 golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Martin Angers at Dec 1, 2013 at 3:27 pm
    The variables declared in the short init statement are scoped to the if statement only (if and optional else). Also, this makes the if statement consistent with the for, which also supports an init statement (without much surprise, since this is the same in most other languages), and the switch.

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Harald Weidner at Dec 1, 2013 at 3:31 pm
    Hello,

    Rasmus Schultz <rasmus@mindplay.dk>:
    What baffles me time and again, is when other statements, separated by
    semi-colons, are rolled into if-statements... for example:

    if _, err: = fmt.Sscanf(line, "%f%f", &radius, &è); err!=nil {
    ....
    }
    To me, this is much more legible:

    _, err: = fmt.Sscanf(line, "%f%f", &radius, &è)

    if err!=nil {
    ....
    }
    I'm hoping there's some subtle *functional* difference that I've missed,
    because this convention leads to otherwise unjustified tangles in the code.
    There is indeed a difference: in your first code snipplet, the variable err
    is local to the scope of the if statement; it invalidates at the closing
    bracket }. In the second example, err is valid even outside the if
    statement, maybe until the end of the function (depending on the context).

    This can well make up a difference, e.g. in the context of named return
    parameters.
    Why do you see this sort of thing so often in Go programs?
    I think the reason for using the first variant is to keep the scope
    of the variable as local as possible.

    Harald

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Rasmus Schultz at Dec 1, 2013 at 8:41 pm
    This can well make up a difference, e.g. in the context of named return
    parameters.

    That makes sense - thanks for the explanation.

    It's certainly a meaningful feature, but what still doesn't make sense to
    me, is the wonky syntax.

    Is there another explicit way to define intermediary variables in a
    delimited scope, without blending them into control structures?

    Thanks
    - Rasmus
    On Sunday, December 1, 2013 10:31:36 AM UTC-5, Harald Weidner wrote:

    Hello,

    Rasmus Schultz <ras...@mindplay.dk <javascript:>>:
    What baffles me time and again, is when other statements, separated by
    semi-colons, are rolled into if-statements... for example:

    if _, err: = fmt.Sscanf(line, "%f%f", &radius, &è); err!=nil {
    ....
    }
    To me, this is much more legible:

    _, err: = fmt.Sscanf(line, "%f%f", &radius, &è)

    if err!=nil {
    ....
    }
    I'm hoping there's some subtle *functional* difference that I've missed,
    because this convention leads to otherwise unjustified tangles in the
    code.

    There is indeed a difference: in your first code snipplet, the variable
    err
    is local to the scope of the if statement; it invalidates at the closing
    bracket }. In the second example, err is valid even outside the if
    statement, maybe until the end of the function (depending on the context).

    This can well make up a difference, e.g. in the context of named return
    parameters.
    Why do you see this sort of thing so often in Go programs?
    I think the reason for using the first variant is to keep the scope
    of the variable as local as possible.

    Harald
    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Dan Kortschak at Dec 1, 2013 at 10:02 pm

    On Sun, 2013-12-01 at 12:41 -0800, Rasmus Schultz wrote:
    Is there another explicit way to define intermediary variables in a
    delimited scope, without blending them into control structures?
    {
      a := expression
      if a == value {
       statements
      }
    }

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Simon place at Dec 1, 2013 at 10:33 pm
    not sure, but one-line version might compile with 'err' on the stack (or
    even in a register?) whereas below might put the var onto the heap and have
    to GC it.
    On Sunday, 1 December 2013 22:02:07 UTC, kortschak wrote:
    On Sun, 2013-12-01 at 12:41 -0800, Rasmus Schultz wrote:
    Is there another explicit way to define intermediary variables in a
    delimited scope, without blending them into control structures?
    {
    a := expression
    if a == value {
    statements
    }
    }
    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Martin Schnabel at Dec 1, 2013 at 10:55 pm

    On 12/01/2013 11:33 PM, simon place wrote:

    not sure, but one-line version might compile with 'err' on the stack (or
    even in a register?) whereas below might put the var onto the heap and
    have to GC it.
    there is absolutely no difference between them.

    if a := 5; a > 3 {
      return
    }

    and

    {
      a := 5
      if a > 3 {
       return
      }
    }

    will output identical assembly listings using go tool 6g -S (apart from
    the line numbers)

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Brandon Peters at Dec 1, 2013 at 10:50 pm
    I know you stated that it doesn't for you (and I'm not saying that it
    should), but it actually reads clearer and faster for me, just as your link
    suggested. "If there's an error doing X..." I realize the code doesn't
    exactly say that but it helpfully allows me to think that. As a reader of
    the code, I'm interested in staying as high-level as possible and being
    allowed to not notice an intermediate assignment is nice. The only reason
    it exists in this example is as feedback about an action that was taken and
    we just happen to commonly express the feedback from actions as assignment
    (via return values).

    In other words, to me, this is an "important" assignment:
    x := addTwo(3) // x = 5

    When I read it, that's what I want to take away in my 0.5 second scan of
    it. The code writer was producing and storing a value. In your original
    example (which is common), the importance is not that anything was assigned
      An assignment occurred only because that's the simplest construct we use
    to know if the action() worked.

    Your separated version makes me mentally stutter. At first I think Sscanf
    is producing an important value rather than being used for side effects
    (not the best function to make my point but you understand). The naming of
    the variable 'err' helps but my brain is still greeted with "here's an
    assignment you should remember!" quickly followed by "oh, no, not
    important, we only assigned so that we could alter downstream flow if
    needed."

    You seem to be saying that assignments and operations should be separated
    from control structures. I'm pretty naive about language design and
    philosophy, is that separation something that generally happens in other
    languages, outside of C++ 'for' loops? Why do you feel like not doing so
    hurts change management in source control? At first blush, I think I feel
    the opposite. With a combined statement there seems to be less chance of
    damaging changes such as removing the error checking or using the first
    return value before checking the error.
    On Sunday, December 1, 2013 12:41:23 PM UTC-8, Rasmus Schultz wrote:

    This can well make up a difference, e.g. in the context of named return
    parameters.

    That makes sense - thanks for the explanation.

    It's certainly a meaningful feature, but what still doesn't make sense to
    me, is the wonky syntax.

    Is there another explicit way to define intermediary variables in a
    delimited scope, without blending them into control structures?

    Thanks
    - Rasmus
    On Sunday, December 1, 2013 10:31:36 AM UTC-5, Harald Weidner wrote:

    Hello,

    Rasmus Schultz <ras...@mindplay.dk>:
    What baffles me time and again, is when other statements, separated by
    semi-colons, are rolled into if-statements... for example:

    if _, err: = fmt.Sscanf(line, "%f%f", &radius, &è); err!=nil {
    ....
    }
    To me, this is much more legible:

    _, err: = fmt.Sscanf(line, "%f%f", &radius, &è)

    if err!=nil {
    ....
    }
    I'm hoping there's some subtle *functional* difference that I've missed,
    because this convention leads to otherwise unjustified tangles in the
    code.

    There is indeed a difference: in your first code snipplet, the variable
    err
    is local to the scope of the if statement; it invalidates at the closing
    bracket }. In the second example, err is valid even outside the if
    statement, maybe until the end of the function (depending on the
    context).

    This can well make up a difference, e.g. in the context of named return
    parameters.
    Why do you see this sort of thing so often in Go programs?
    I think the reason for using the first variant is to keep the scope
    of the variable as local as possible.

    Harald
    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Rasmus Schultz at Dec 3, 2013 at 1:54 pm
    Thanks for your insights, guys - this looked horribly awkward to me at
    first, but I think I'm getting the hang of it.

    Your perspective was really useful, Brandon - I'm starting to see it your
    way :-)

    - Rasmus
    On Sunday, December 1, 2013 5:50:04 PM UTC-5, Brandon Peters wrote:

    I know you stated that it doesn't for you (and I'm not saying that it
    should), but it actually reads clearer and faster for me, just as your link
    suggested. "If there's an error doing X..." I realize the code doesn't
    exactly say that but it helpfully allows me to think that. As a reader of
    the code, I'm interested in staying as high-level as possible and being
    allowed to not notice an intermediate assignment is nice. The only reason
    it exists in this example is as feedback about an action that was taken and
    we just happen to commonly express the feedback from actions as assignment
    (via return values).

    In other words, to me, this is an "important" assignment:
    x := addTwo(3) // x = 5

    When I read it, that's what I want to take away in my 0.5 second scan of
    it. The code writer was producing and storing a value. In your original
    example (which is common), the importance is not that anything was assigned
    An assignment occurred only because that's the simplest construct we use
    to know if the action() worked.

    Your separated version makes me mentally stutter. At first I think Sscanf
    is producing an important value rather than being used for side effects
    (not the best function to make my point but you understand). The naming of
    the variable 'err' helps but my brain is still greeted with "here's an
    assignment you should remember!" quickly followed by "oh, no, not
    important, we only assigned so that we could alter downstream flow if
    needed."

    You seem to be saying that assignments and operations should be separated
    from control structures. I'm pretty naive about language design and
    philosophy, is that separation something that generally happens in other
    languages, outside of C++ 'for' loops? Why do you feel like not doing so
    hurts change management in source control? At first blush, I think I feel
    the opposite. With a combined statement there seems to be less chance of
    damaging changes such as removing the error checking or using the first
    return value before checking the error.
    On Sunday, December 1, 2013 12:41:23 PM UTC-8, Rasmus Schultz wrote:

    This can well make up a difference, e.g. in the context of named return
    parameters.

    That makes sense - thanks for the explanation.

    It's certainly a meaningful feature, but what still doesn't make sense to
    me, is the wonky syntax.

    Is there another explicit way to define intermediary variables in a
    delimited scope, without blending them into control structures?

    Thanks
    - Rasmus
    On Sunday, December 1, 2013 10:31:36 AM UTC-5, Harald Weidner wrote:

    Hello,

    Rasmus Schultz <ras...@mindplay.dk>:
    What baffles me time and again, is when other statements, separated by
    semi-colons, are rolled into if-statements... for example:

    if _, err: = fmt.Sscanf(line, "%f%f", &radius, &è); err!=nil {
    ....
    }
    To me, this is much more legible:

    _, err: = fmt.Sscanf(line, "%f%f", &radius, &è)

    if err!=nil {
    ....
    }
    I'm hoping there's some subtle *functional* difference that I've missed,
    because this convention leads to otherwise unjustified tangles in the
    code.

    There is indeed a difference: in your first code snipplet, the variable
    err
    is local to the scope of the if statement; it invalidates at the closing
    bracket }. In the second example, err is valid even outside the if
    statement, maybe until the end of the function (depending on the
    context).

    This can well make up a difference, e.g. in the context of named return
    parameters.
    Why do you see this sort of thing so often in Go programs?
    I think the reason for using the first variant is to keep the scope
    of the variable as local as possible.

    Harald
    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Gerard at Dec 2, 2013 at 7:45 am

    Is there another explicit way to define intermediary variables in a
    delimited scope, without blending them into control structures?
    I think the best way is to have small functions. That way you still have
    oversight of the variables and there is no need for a delimited scope.

    With the bigger functions (e.g. > 100 lines), the approach of Dan Kortschak
    is often used. Most of the time I see it in repeating stuff with small
    deviations, such as tests.

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Chris dollin at Dec 1, 2013 at 5:19 pm
    consider what would happen in an else-if.
    On Dec 1, 2013 2:43 PM, "Rasmus Schultz" wrote:

    Hello, Gophers :-)

    I'm sure this must have been asked before, but I searched the forums and
    the Wiki, and the closest thing I could find to an explanation, was this:


    https://code.google.com/p/go-wiki/source/browse/SimultaneousAssignment.wiki?repo=wiki

    So I get the part about simultaneous assignment, but that's not really my
    question...

    What baffles me time and again, is when other statements, separated by
    semi-colons, are rolled into if-statements... for example:

    if _, err: = fmt.Sscanf(line, "%f%f", &radius, &θ); err!=nil {
    ....
    }

    I understand how it works, or at least I think so ;-)

    But I don't understand why anyone would do that?

    To me, this is much more legible:

    _, err: = fmt.Sscanf(line, "%f%f", &radius, &θ)

    if err!=nil {
    ....
    }

    I get that the first statement in this example is related to the
    if-statement, but it isn't *part* of the if-statement, and it makes the
    if-statement really hard to read, because the first statement isn't part of
    the *condition*, which is what I expect to see after the word *if*.

    Why do you see this sort of thing so often in Go programs?

    Does it serve a purpose, other than garbling the code (and complicating
    change management in source control) in an attempt to communicate the fact
    that the if-statement is *dependent* on the other statement?

    I'm hoping there's some subtle *functional* difference that I've missed,
    because this convention leads to otherwise unjustified tangles in the code.

    It brings to mind the "backwards if-statements" in Ruby, where if
    if-statement and *pre*-condition is placed *after* the conditional
    statement - to me, this sort of thing is *clever* but not *simple*, and
    from what I've seen so far, the Go language (and community) always stays
    away from *clever* whenever it is possible to keep things *simple*.

    Only a few days in, but I love the simplicity of the Go language thus far
    :-)

    But this one baffles me.

    Explain, please? :-)

    thanks!

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Kevin Gillette at Dec 2, 2013 at 5:21 am
    I personally use the included short-declaration form in situations like:

    if scanner.Err(); err != nil { }


    but not:

    if err := Function(with, lots, of, arguments); err != nil { }


    as the latter form, in my opinion, sacrifices clarity where the former does
    not. Additionally, if the right-hand-side expression produces multiple
    values, or for whatever reason I'm inclined to use regular assignment
    instead of a short declaration, I'll choose to move the
    assignment/declaration outside of the if statement.

    Regarding scoping: it's not usually a critical aspect of deciding whether
    to use short decl's within an if statement. Rather, it's most useful when
    assignments need to occur within if-else chains that apply to the rest of
    the chain, for example:

    if x := F1(); x > 5 {
    // ...
    } else if y := F2(); y < 10 {
    // ...
    } else if z := F3(); z != 20 && x > 0 && y < 3 {
    // ...
    } else {
    // ...
    }

    It becomes much longer to do the above without being able to embed
    declarations into control structures.

    If the language had something like disconnected if-else chains, i.e.:

    x := F1()
    if x > 5 {
    // ...
    }
    y := F2();
    else if y < 10 {
    // ...
    }
    z := F3()
    else if z != 20 && x > 0 && y < 3 {
    // ...
    } else {
    // ...
    }

    Then some control-flow tasks could be simplified, and there'd be no need to
    have declaring-if's, though I doubt such a thing would be an improvement to
    readability (especially considering potential abusive cases, such as if an
    'else' is hundreds of lines from the closing brace of the previous 'if').
    On Sunday, December 1, 2013 7:43:27 AM UTC-7, Rasmus Schultz wrote:

    Hello, Gophers :-)

    I'm sure this must have been asked before, but I searched the forums and
    the Wiki, and the closest thing I could find to an explanation, was this:


    https://code.google.com/p/go-wiki/source/browse/SimultaneousAssignment.wiki?repo=wiki

    So I get the part about simultaneous assignment, but that's not really my
    question...

    What baffles me time and again, is when other statements, separated by
    semi-colons, are rolled into if-statements... for example:

    if _, err: = fmt.Sscanf(line, "%f%f", &radius, &θ); err!=nil {
    ....
    }

    I understand how it works, or at least I think so ;-)

    But I don't understand why anyone would do that?

    To me, this is much more legible:

    _, err: = fmt.Sscanf(line, "%f%f", &radius, &θ)

    if err!=nil {
    ....
    }

    I get that the first statement in this example is related to the
    if-statement, but it isn't *part* of the if-statement, and it makes the
    if-statement really hard to read, because the first statement isn't part of
    the *condition*, which is what I expect to see after the word *if*.

    Why do you see this sort of thing so often in Go programs?

    Does it serve a purpose, other than garbling the code (and complicating
    change management in source control) in an attempt to communicate the fact
    that the if-statement is *dependent* on the other statement?

    I'm hoping there's some subtle *functional* difference that I've missed,
    because this convention leads to otherwise unjustified tangles in the code.

    It brings to mind the "backwards if-statements" in Ruby, where if
    if-statement and *pre*-condition is placed *after* the conditional
    statement - to me, this sort of thing is *clever* but not *simple*, and
    from what I've seen so far, the Go language (and community) always stays
    away from *clever* whenever it is possible to keep things *simple*.

    Only a few days in, but I love the simplicity of the Go language thus far
    :-)

    But this one baffles me.

    Explain, please? :-)

    thanks!
    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • RickyS at Dec 3, 2013 at 9:20 pm
    When I first saw this I immediately "Knew" what it was for: To capture
    back the screen real estate used up by *fmt* when it puts things on
    multiple lines, such as the closing curly brace.

    Now that I'm a Real Gopher I still believe that; The scope excuse is lame,
    since the compiler can figure that out from usage. And you shouldn't
    duplicate variable names in the same function anyway. Well, maybe for
    'err'.

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Kevin Gillette at Dec 3, 2013 at 9:55 pm
    We don't care much about screen real-estate, and we care more about
    consistency in the number of characters-per-line than we do about
    minimizing the number of lines. The fact that if-declarations can save a
    line is a superficial quality, and it really just does two things:

        1. It provides a more structured, less error-prone way to achieve the
        effect that C and similar languages have due to their assignments being
        expressions. Thus `if(x = y / 2) {}` in C can be represented in Go with `if
        x = y / 2; x != 0 {}`.
        2. For languages in which assignments may only be statements, control
        flow becomes trickier in some situations (example here<https://groups.google.com/d/msg/golang-nuts/__NG4nQJFMo/35ZPdeakCWAJ>),
        which demands use of switch-fallthrough semantics, or when that's not
        flexible enough, redundant computations or breaking apart the if/else chain
        in conjunction with goto or temporary variables. Go avoids that mess which
        this mechanism.
    On Tuesday, December 3, 2013 2:20:20 PM UTC-7, RickyS wrote:

    When I first saw this I immediately "Knew" what it was for: To capture
    back the screen real estate used up by *fmt* when it puts things on
    multiple lines, such as the closing curly brace.

    Now that I'm a Real Gopher I still believe that; The scope excuse is
    lame, since the compiler can figure that out from usage. And you shouldn't
    duplicate variable names in the same function anyway. Well, maybe for
    'err'.
    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Rasmus Schultz at Dec 4, 2013 at 2:02 pm
    In some situations this can also conserve memory, right? If inside a loop,
    you have several conditions that require different intermediary results,
    each of those can be discarded along the way, instead of having to keep
    them around until you exit the parent scope.

    I also like that you don't clutter the parent scope with various
    intermediary variables - in a complex function, it raises fewer questions
    (on the part of the reader) about which variables are in scope and why...
    in many other languages, you can accumulate many local variables in the
    scope of a function, for no apparent reason, unless you explicitly
    delete/unset those variables after each use.

    Yeah, this totally makes sense to me now :-)


    On Tue, Dec 3, 2013 at 4:48 PM, Kevin Gillette
    wrote:
    We don't care much about screen real-estate, and we care more about
    consistency in the number of characters-per-line than we do about
    minimizing the number of lines. The fact that if-declarations can save a
    line is a superficial quality, and it really just does two things:

    1. It provides a more structured, less error-prone way to achieve the
    effect that C and similar languages have due to their assignments being
    expressions. Thus `if(x = y / 2) {}` in C can be represented in Go with `if
    x = y / 2; x != 0 {}`.
    2. For languages in which assignments may only be statements, control
    flow becomes trickier in some situations (example here<https://groups.google.com/d/msg/golang-nuts/__NG4nQJFMo/35ZPdeakCWAJ>),
    which demands use of switch-fallthrough semantics, or when that's not
    flexible enough, redundant computations or breaking apart the if/else chain
    in conjunction with goto or temporary variables. Go avoids that mess which
    this mechanism.
    On Tuesday, December 3, 2013 2:20:20 PM UTC-7, RickyS wrote:

    When I first saw this I immediately "Knew" what it was for: To capture
    back the screen real estate used up by *fmt* when it puts things on
    multiple lines, such as the closing curly brace.

    Now that I'm a Real Gopher I still believe that; The scope excuse is
    lame, since the compiler can figure that out from usage. And you shouldn't
    duplicate variable names in the same function anyway. Well, maybe for
    'err'.
    --
    You received this message because you are subscribed to a topic in the
    Google Groups "golang-nuts" group.
    To unsubscribe from this topic, visit
    https://groups.google.com/d/topic/golang-nuts/__NG4nQJFMo/unsubscribe.
    To unsubscribe from this group and all its topics, send an email to
    golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Jonathan at Dec 4, 2013 at 5:35 pm
    While we're on the topic I'd like to see something like 1) below in go 1.3
    or 2.0

    1) Hypothetical switch statement with default switch value and case
    expressions extended with simple assignment statements.

    // SendJob sends Job j into queue q at the server
    // RFC1179 allows multiple jobs per SendJob command, we don't
    func (s *Server) SendJob(queue string, j Job) (err error) {
    var b byte
    switch {
    case err = s.sendCommand(queue, ReceiveJob, nil, err); err != nil:
    case b, err = s.readByte(); err != nil:
    case b != 0:
    err = fmt.Errorf( "Invalid command ack %d", b )
    case err = s.jobSendControlFile(j); err != nil:
    case err = s.jobSendDataFile(j); err != nil:
    }
    return
    }

    2) (Current) If statements with expressions extended with simple
    assignment statements.

    // SendJob sends Job j into queue q at the server
    // RFC1179 allows multiple jobs per SendJob command, we don't
    func (s *Server) SendJob(queue string, j Job) (err error) {
    var b byte
    if err = s.sendCommand(queue, ReceiveJob, nil, err); err != nil {
    return
    }
    if b, err := s.readByte(b); err != nil {
    return
    }
    if b != 0 {
    err = fmt.Errorf( "Invalid command ack %d", b )
    return
    }
    if err = s.jobSendControlFile(j); err != nil {
    return
    }
    3) Just for completes, same code with error arguments as suggested earlier
    in the thread.

    // SendJob sends Job j into queue q at the server
    // RFC1179 allows multiple jobs per SendJob command, we don't
    func (s *Server) SendJob(queue string, j Job) (err error) {
             var b byte
             switch {
             case !s.sendCommand(queue, ReceiveJob, nil, &err):
             case !s.readByte( b, &err):
             case b != 0:
                     err = fmt.Errorf( "Invalid command ack %d", b )
             case !s.jobSendControlFile(j, &err):
             case !s.jobSendDataFile(j, &err):
             }
             return
    }

    I think 1) is actually the clearest, though 2) is a close second. Version
    3) I have to read twice, so to speak, to see that the func result is
    consistently the error state. This despite the fact 3) is the actual code
    in use. It was an experiment. I don't really like it.

    Jonathan

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Kevin Gillette at Dec 4, 2013 at 7:23 pm

    On Wednesday, December 4, 2013 10:35:25 AM UTC-7, Jonathan wrote:
    1) Hypothetical switch statement with default switch value and case
    expressions extended with simple assignment statements.
    There is a point somewhere between if/else chains and switch statements in
    which some problems would be best approached simultaneously using the
    features of both. When I've encountered those situations, I have often
    thought it'd be simpler to have the ability to make declarations in the
    case line. Certain optimizations in specific cases would have to be
    discarded when this would be used, however.

    2) (Current) If statements with expressions extended with simple
    assignment statements.

    // SendJob sends Job j into queue q at the server
    // RFC1179 allows multiple jobs per SendJob command, we don't
    func (s *Server) SendJob(queue string, j Job) (err error) {
    var b byte
    if err = s.sendCommand(queue, ReceiveJob, nil, err); err != nil {
    return
    }
    if b, err := s.readByte(b); err != nil {
    // you're shadowing err here -- it used to be this would always result in
    nil being returned, though now this will fail to compile.

                     return
    }
    if b != 0 {
    err = fmt.Errorf( "Invalid command ack %d", b )
    return
    }
    if err = s.jobSendControlFile(j); err != nil {
    return
    }
    Since the return statements make each 'if' after the first behave exactly
    like an else-if, why not condense these into a single if-else chain? If
    it's a matter of clarity, my opinion in these cases is that it should
    always be condensed into an if-else, or assignments should be moved out of
    the if statement. In this case, I would have just used an unnamed return
    parameter, an if-else chain with colon-equals instead of the separate var
    declaration, and explicit returns.

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Kevin Gillette at Dec 4, 2013 at 7:24 pm

    On Wednesday, December 4, 2013 7:02:17 AM UTC-7, Rasmus Schultz wrote:
    In some situations this can also conserve memory, right? If inside a loop,
    you have several conditions that require different intermediary results,
    each of those can be discarded along the way, instead of having to keep
    them around until you exit the parent scope.
    Yes, inner scopes *could* be popped off the stack at the time that scope is
    exited as you describe, though that also could be done simply with
    last-time-of-use analysis (which could occur well before end of scope).
    However, given Go's dynamic stack implementation, the overhead of that,
    especially around stack size thresholds, would be too expensive to be worth
    doing. At function entry, the runtime knows exactly how much space to
    allocate for all scopes within that function, because it's statically known
    at compile time; if the space that a function temporarily uses (such as at
    the beginning of a function, before an infinite loop) is large enough to
    be concerned about, then for organizational reasons it may be migrating
    that early code into a separate function anyway.

    In practice, more useful than space reclamation is stack space reuse. For
    example, in <http://play.golang.org/p/_a0k7ARpXp>, x and y are in unrelated
    scopes, thus by the type y is declared, x is no longer used, and thus y
    could have the same address as x in this case, but the current gc compiler
    implementation does not make that optimization. I'm guessing that either
    the variables are intentionally given separate stack slots to aid in some
    debugging system I'm unaware of (though correct single-step debugging
    should be able to extrapolate the correct variable name for a given stack
    address based on the instruction pointer), or compiler analysis is not
    sufficiently developed yet to make this optimization.

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedDec 1, '13 at 2:43p
activeDec 4, '13 at 7:24p
posts18
users13
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase