I've been playing around with Lua recently. It's a really sweet little language. A particular highlight is its "tables", which are generalized associative arrays that can have keys of any type. (Most languages only allow strings and/or numbers.) It also has pretty nice uniform handling of multiple function arguments, multiple return values, and multiple assignment.

A frequent topic of discussion on the Lua list is the fact that Lua does not have a switch/case statement. Most of the people who propose how one should be added tend to copy other languages which can only switch on one value at a time. I think it would me more in keeping with the rest of Lua to have a multi-valued case statement. I also quite like the idea of making it capable of ML-style pattern matching and variable binding.

The syntax I have in mind is as follows. I'm using ? to mean 0 or 1 of the following, * to mean 0 or more, and + to mean 1 or more.

case explist1 +(+(match patlist ?(if exp) ) then block) ?(else block) end

As in C, multiple matches for a given block are expressed using multiple match clauses, instead of the alternatives being listed in a single clause as in Modula. Each match can be guarded by a conditional expression; when it evaluates to false the match fails and later ones are tried. The statements followingare evaluated if one of the precedinges succeeds. You can put a "default" or "otherwise" case after an. (I quite like the re-use of keywords, though perhaps it is too cute.) All variables bound by theclauses are visible in the following block; the variables in a pattern list must all be different; if the clause binding a variable isn't the one that matched then the variable's value is nil.

Lua also needs more expressive exception handling - I'm not too fond of its "protected call" mechanism. It would be more palatable if it were dressed up in something like:

try block +(+(catch patlist ?(if exp) ) then block ) ?(finally block ) end

A useful bit of syntactic sugar is to be able to declare functions in a pattern matching style instead of an argument-passing style, so:

function (...) case ... match a, b, c blah blah end end

function match a, b, c blah blah end

could be more concisely written:

I'm still pondering the syntax for pattern lists. A basic principle is that all direct comparisons should be against constants, so that the match can be compiled into a table lookup against a constant table. This means only numbers and strings - other objects in Lua either do not have compile-time expressions (C userdata) or have expressions that do not denote constant values but instead describe how to create new objects at run-time (function closures and tables). I also want to allow indirect comparisons against table elements, so that it's possible to match against structured data. Finally there needs to be a way of binding a variable to the value being matched against.

I do not intend to support exact matches against tables: only the elements that you specify in the match will be checked and if the table has more elements they will be ignored. This is because the extra check to make the match exact may not be entirely trivial to implement, and because it makes code brittle in the presence of unexpected values squirreled away in a table - it's quite common in prototype-based object systems to add methods to an object without co-operation from the code that created it.

So the basic syntax for a pattern to match against simple constants or to bind a variable is:

String | Number | Name

"{" pattern *( "," pattern ) "}"

Matching against the first few integer indexed elements of a table in list style is also simple:

It's also useful to both match against a table and bind a variable, so that you can refer to the table in the later statements. (It isn't possible to reconstruct the table because it may have extra elements, and even if it were possible it would be inefficient and the result would have a different identity.) It's also useful to both match a constant and bind a variable, if you have multiple match clauses: case f() match 3 match 4 then -- did f return three or four? I'm still unsure about the syntax for matching and binding. Some possibilities are:

pattern and pattern pattern pattern Name "=" pattern Name "==" pattern

The idea of "and" patterns is that you are matching both the left-hand side and the right-hand side. It suggests that there should also be "or" patterns, as in case f() match 3 or 4 then ... In MCPL you get the same effect as and by just writing the patterns side-by-side, and (like sh) | is used instead of or.

The idea of using "=" is to make binding in a pattern look like assignment, whereas "==" is supposed to be like an assertion. However these get problematic when we try to fit key/value style table matching into the syntax. Table constructors in Lua look like:

tableconstructor = "{" ?fieldlist "}" fieldlist = field *(fieldsep field) ?fieldsep fieldsep = "," | ";" field = "[" exp "]" "=" exp | Name "=" exp | exp

table[key]

table.name

table["name"]

(The first form of field is by analogy with theform of index expression. The second is likeindexing, which is syntactic sugar for. The last is for list-style construction, where the value is assigned to the next integer index starting from 1.)

If we follow constructor syntax closely, we get the serious difficulty that a pattern like { foo = bar } isn't clear which name is the table index and which is the variable being bound. This probably indicates that = should be avoided.

Perhaps the solution is to use an arrow to indicate which way values flow, as in:

tablepattern = "{" ?fieldpatterns "}" fieldpatterns = fieldpat *(fieldsep fieldpat) ?fieldsep fieldpat = "[" (String | Number) "]" "->" pattern | Name "->" pattern | pattern pattern = String | Number | Name | pattern and pattern | pattern or pattern

->

This seems reasonably OK, I think. It also suggests adding a free-standing match operatorthat produces a boolean result (and probably should not bind variables).