lua-users home
lua-l archive

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

On 6-Oct-05, at 5:59 AM, Doug Rogers wrote:

with them. I'd prefer 'break when' and 'continue when'. The 'when'
keyword could then be used to support a 'case' statement implementation.
And now we're off on another grand exploration!

Well, ok, another update (same url: <>). This one adds back the 'break' and 'continue' statements (well, adds the continue statement would be a better phraseology, I guess), and adds named loop labels. (See below.)


  <condition>   ::= [ <name-list> '=' <expr-list> 'satisfies' ] <expr>

  <for-binding> ::= <name-list> ('=' | 'in') <expr-list>
   -- Not quite accurate, but it hasn't changed: I just put it in
   -- for completeness

  <label>       ::=  ':' <name>
   -- labels *follow* the keyword, which makes ':' unambiguous

<iterator> ::= [ 'for' <for-binding> ] 'do' [<label>] <block> 'end'

                ::= <shivers-iteration-control> | <c-iteration-control>

                ::= ('unless' | 'until' | 'when' | 'while') <condition>

                ::= ('when' | 'unless') <condition>

::= ('break' | 'continue') [ <label> ] [ <iteration-condition> ] -- Note: If the <iteration-control> is not conditional, it must be the last -- statement in the block. There's actually no syntactic need for this.

  <if-condition> ::= <condition> 'then' <block>
  <if-statement> ::= 'if' <if-condition>
                          [ 'elseif' <if-condition> ]*
                          ['else' <block>]

I hope that's clear.

The scope of a <condition> extends to the end of the <block>; that is, in the case of <*-iteration-control>, it goes to the end of the iteration block (assuming that no exit is taken, otherwise the point is somewhat moot); in the case of an <if-condition> it goes to the end of the following <block> (and terminates with the 'elseif' or 'else' or 'end'.) The latter is not the same as C++ scoping rules, I don't believe, but it seemed more natural to me, after trying both variants. The 'satisfies' clause is mandatory even though in many cases you end up writing:

   if a = foo() satisfies a then ... end

because if it were optional, it would introduce the classic problem with writing = instead of == and changing semantics. I make this typo a lot, so I wasn't about to make it possible for the compiler to not complain.

After I added the loop labels, I had to try them out at least once. I can't say that the experiment was a success, and I'm starting to wonder if it's really a good idea aside from really simple cases, and possibly not even then. Anyway, be your own judge (and feel free to criticize the code.) The experiment is in <> (the code itself can be downloaded at <>), which consists of three implementations of the 8-queens problem (actually, the n-queens problem). The first one is a standard recursive backtracking solution; the second one is a functional recursive backtracking solution (i.e. no mutable state); the third one is a purely iterative solution using labelled iteration blocks. I find the third one almost unreadable. (It wasn't easy to write, either.) Moreover, it has no speed benefits.

The tarball also includes a C implementation using the functional recursive backtracking solution; it demonstrates that heap-allocation is not intrinsic to that style, although I don't off-hand know how to accomplish that feat in languages other than C, which is an odd commentary.

Let me know if there are any unsquashed bugs. I might even fix them. :)