lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Fri, Jan 28, 2011 at 8:04 AM, Jim Whitehead II <jnwhiteh@gmail.com> wrote:
>>  local x
>>  do
>>    x = 1
>>  :loop:
>>    if x > 10 then break :exit: end
>>    print(x)
>>    x = x + 1
>>    break :loop:
>>  :exit:
>>  end
>
> Reading this code it is incredibly confusing to me, since it seems
> that 'break' is simply the 'goto' keyword in new clothing.

That example was merely to illustrate the expressive power of the
construct in emulating other control structures.  You may want this
expressiveness for code generation purposes, and it may also be nice
to think of the Lua `for` loop as mere syntactic sugar that expands or
compiles into the above code.  I don't think the form is odd, for the
code would be nearly identical in a lower level language lacking
formal loop structures, just with different syntax--e.g. `break`
replaced with `goto`.  However, my use of `break` is semantically a
much more restrictive form of `goto` for the following reason....

> I also sincerely dislike the syntax of labels at any point in the block-- I
> much prefer the other proposal where the only place a label can occur
> is after the beginning of a block and where the semantics of the break
> keyword are clear and easy to define.

Restriction of labels to only the beginning of a block is exactly what
the proposed grammar does:

   `do` block {label block} `end`

Such blocks really are blocks in the usual sense, as this example demonstrates:

  local x = 2
  do
    local x = 1
    print(x)
  :label1:
    print(x)
  end
  -- prints 1 2

And if you have this:

  do :start: f() :finish: end

it really is three blocks, the first and last of which have no statements.

A `break` inside a block first breaks out of the current block (e.g.
destroys local variables) and then jumps to the start of the block
named in the label.  If the break lacks a label, the label is assumed
to be :break: .  Each loop implicitly has an invisible :break: block
at the end, thereby preserving consistency with Lua 5.1 behavior, as
shown here:

  for i=1,10 do
    local x = io.read'*n'
    if not x then
      print 'bye'
      break  -- equivalent to `break :break:`, exiting the loop
    elseif x < 0 then
      print 'ignoring that'
      break :continue:  -- jumps to the :continue: block
    end
    f(x)
   -- for loops contain an invisible :continue: block here
  end
  -- for loops also contain an invisible :break: block here.

If you "expand" this `for` loop (which again is only syntactic sugar),
it would look like this:

  do
    local i = 1
    do
    :redo:
      local x = io.read'*n'
      if not x then
        print 'bye'
        break :break:
      elseif x < 0 then
        print 'ignoring that'
        break :continue:
      end
      f(x)
    :continue:
      x = x + 1
      if x <= 10 then
        break :redo:
      end
    :break:
    end
  end