lua-users home
lua-l archive

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


In message <199704131744.NAA03710@flatcoat.cs.virginia.edu>
                                                      Norman Ramsey writes:
 > I felt the need for a case statement in Lua, so I added one.
 <snip>
 > I borrowed syntax from Modula-3 for the case statement (with one
 > slight change); here's an example:
 > 
 >   x = "bar"
 >   
 >   case x of
 >   | "foo" => y = 1
 >   | "bar" => y = 2
 >   else => y = 99  
 >   end

... and then there was some discussion of the aesthetics. I don't really
like the rather cryptic tokens '|' and '=>' either; they're too terse and
mathematical-looking for a language that is supposed to be friendly to
"casual" users, as Lua is (and all extension languages *should* be). Also,
at present, all control tokens are english words and all infix operators
are (!isalnum()); it would be a shame to break this consistency.

Looking at the above, (and the patch to lua.stx) I see:

  SwitchIntroToken <expr> ExprTerminalToken
    {<case>}1
  ListTerminalToken

where:

  <case> ::=  CaseIntroToken <value> ValTerminalToken <statement>   |
              DefaultCaseToken <statement>

But as Norman says, it would be much better if the statements were replaced
with blocks of statements. If this were done, I think it would be much more
consistent with the rest of Lua if we had:

  <case> ::=  <value> ValTerminalToken <block> BlockTerminalToken  |
              DefaultCaseToken <block> BlockTerminalToken

... and both ListTerminalToken and BlockTerminalToken were the good old "end"
used everywhere else. Norman has the following:

SwitchIntroToken   ::= "case"
ExprTerminalToken  ::= "of"
CaseIntoToken      ::= "|"
ValTerminalToken   ::= "=>"
DefaultCaseToken   ::= "else"
ListTerminalToken  ::= "end"

But I would suggest something like:

SwitchIntroToken   ::= "with"
ExprTerminalToken  ::= "choose"
ValTerminalToken   ::= "does"
DefaultCaseToken   ::= "default"
BlockTerminalToken ::= "end"
ListTerminalToken  ::= "end"

Yielding a translated and expanded example:

  with x choose
    "foo" does
      y = 1  z = "A"  end
    default
      y = 99  z = ""  end
    "bar" does
      y = 2  z = "B"  end
  end

Notice the arbitrary placement of the default case; "else" looks like it
*has* to go at the end but "default" looks OK anywhere. (Read on to see
why I don't think we need to force it to be last.)

I'm not too sure about "with x choose", however, and I'd welcome a better
suggestion...

I take Norman's point in his later post about explicit unique tokens
delimiting the segments of all control constructs, and omitting
CaseIntroToken ('|' in Norman's implementation) seems to break this,
but the inside of a case list is a special environment, and I have a
second reason:

As implemented Norman's case construct is not a lot more efficient than
a long "if elseif... else end", although the introduction of DUP helps.

In my original post in response to LHF's "wishlist" call, asking for a case
construct I envisaged it being used when you had, say, >10 choices to cover
and being implemented by using the value of the control expression to index a
hidden table of anonymous functions, each of which would take no parameters
and return nothing.

This would give a real efficiency gain when there are a lot of choices by
leveraging Lua's built-in hashing abilities (Is this not what case statements
are _for_?). The above syntax would, I think, be cleaner if this method were
used, and the "default" case can go anywhere; it is just another table entry
like the rest, but with a special unique index...



--  Mark Ian Barlow                Non-Linear Control Consultants Ltd.
    -----------------------------------------------------------------
    Mark@nlcc.demon.co.uk            Voice / Fax: +44 (0)1207 562 154