On Wed, Jul 26, 2017 at 08:44:46AM -0700, Christoph Berger wrote:

> > someone shared [this question](
> > https://www.reddit.com/r/golang/comments/6paqc0/bug_that_caught_me_with_range/)
> >  
> > on reddit. I must say, that I'm surprised by the behavior myself. I would 
> > have expected
> > for i = range v
> > to be semantically equivalent to
> > for i = 0; i < len(v); i++
> > and don't really understand the reasoning behind choosing different 
> > semantics. Note, that the difference only exists, if i is declared outside 
> > of the loop, that is, this is solely about the behavior after exiting the 
> > loop-body.
> >
> > I'd greatly appreciate some explanation :)
> An attempt to explain this by looking at the C-style loop only:
> 
> The classic C-style for loop
> 
> for i:=0; i<len(v); i++ {...}
> 
> is equivalent to
> 
> for i:=0; i<len(v); {
>     // do something with i
>     i++ // This is always the very last statement in the loop body
> }
> 
> The loop body runs from 0 to len(v)-1 only, because the last increment of i 
> to len(v) stops the loop, and no further iteration occurs. The code in the 
> loop body never sees i being set to len(v). 
> 
> And that's the same behavior as with the range operator. 
> 
> The code in the Reddit post takes advantage of the fact that the last 
> increment of the C-style loop can be observed outside the loop, for 
> detecting if the loop stopped early. This is a neat side effect that is not 
> possible with the range operator.

I would point out that both Axel and you are off a tiny bit from what
actually happens ;-)

In a for loop which uses a short variable declaration, that variable's
scope is confined to the for *statement* itself, and is also visible in
the loop's body because its scope is defined to be nested in that of the
loop statement.  This means in a loop like

  for i := 0; i < len(s); i++ {
  }

the variable "i" is not accessible after the closing brace.

The actual "problem" stated in that Reddit post is different: it uses a
variable defined outside the "for" loop:

  var i int
  for i = 0; i < len(v); i++ {
  }

As you can see, the loop merely uses that variable; it existed before
the loop and continued to live on after it finished executing.

To recap what others have already written, since the for loop's post
statement is defined to be executed after each execution of the body
(unless it was exited by means of executing `break` or `return`), that

  i++

statement gets executed, the condition evaluates to false, and the loop
exits -- with the variable "i" having the value equal to len(v).

One could do

  var x int

  for i := 0; i < len(v); i, x = i+1, x*2 {
  }

and get even more interesting effect on the variable "x" after the loop
finishes executing ;-)

-- 
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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to