lua-users home
lua-l archive

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



On 28-Sep-05, at 9:00 PM, jrs@tbrve.net wrote:

My example 'continue' using repeat ... until true 'misused' that looping construct, turning it into a simple block by making the iteration control
conditional superfluous.

Indeed, leading to anti-self-documenting code. I've seen the same thing in C, occasionally preceded with a comment like "this 'do' is only to allow the use of 'break´". I've always thought that it would be better to use a goto in such cases, since (may I not be smitten by Djikstra's ghost) a 'goto' with a well-chosen label is easier to understand than a misused iteration construct.

Having said that, I do not favour adding 'goto' to Lua.

The special cases about what's in an 'environment frame' for a block when
it has a conditional attached have created a surprise.  This surprise
suggests to me that the 'block' as a construct should be 'promoted' and
reconsidered independently of the looping control conditional constructs
 with which it's usually very closely associated.

Lua does not associate 'blocks' with looping constructs. The various clauses
in 'if' statements are 'blocks', for example (both syntactically and
semantically). The manual explicitly states "The scope of variables begins
at the first statement after their declaration and lasts until the
end of the innermost block that includes the declaration." That clearly
identifies "blocks" as a scope construction, which seems reasonable to
me. It was, therefore, a real surprise to find that the 'until' clause
of the 'repeat' instruction was inside the scope of the 'block'.

On the other hand, a 'block' in Lua is *also* (more or less) a 'basic block' in the sense usually used in structured programming analysis. The internals
of Lua suggest that a block (as defined by a Block structure) is really
more oriented towards compiling basic blocks than towards maintaining
scope. This does not need to be ambiguous; keeping the two concepts
completely in synch is consistent with Lua's minimalist design.

It's worth noting that internally, all loop constructs consist of two
nested Blocks: the outer block, which is invisible in the source code,
is used to provide an execution context for the 'break' statement,
while the inner block is used to contain scope. Since the loop statement
itself is in the outer block, 'break'ing from the inner block would be
tantamount to 'continue'. This observation would have lead to a much
cleaner implementation of the continue patch, although it still would
have failed for the new semantics of 'repeat'.

The aspect of Lua that really sets it apart from other languages for me
is that it and its syntax revolve around manipulating a few carefully
selected and useful computing constructs. The 'block' may be one of those
constructs.

I agree with this. (In fact, I wouldn't have said "may be one".)

I also wonder what motivated the change in repeat ... until ... . That is, what new use or better use of repeat ... until ... was envisioned that
this change was to make possible?

I also wonder about this. The actual implementation of "until <expr>"
generates the same code as would have been generated by replacing the
clause with "if <expr> then break end; until true" (aside from a small
optimization in the case that no upvalues are created in the block).
This suggests that it might be better to make "until" into a very
simple macro-expansion, and terminate 'repeat' blocks with 'end':

repeat
  -- do something
  until z < 3
end

If 'until' is a statement (expanding into "if <cond> then break end")
then it could appear anywhere inside the loop, even several times;
allowing the unification of pre-tested ("while") loops with post-tested
("repeat") loops (and adding mid-tested loops as well):

repeat
  until p == nil
  --- do something
  loops = loops + 1
  until loops > 1e4
  p = p.next
end

However, I'm not convinced that this adds anything in the way of
readability; it is simply more compact than:

  if loops > 1e4 then
    break
  end

It does, however, realign blocks and scopes, which is a good thing.

Everyone will have their own deeply-held and radically distinct
views about what "looks better". I personally prefer a minimum
set of powerful constructs than a large confusing set of one-shot
constructs. In fact, I would favour replacing the numeric 'for'
with a 'range' basic function:

  for i in range(1, 100, 4) do ... end

even though it might come at a small price at execution time. (Making
the price small would be the challenge, of course.)