case statement for Lua

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

case statement for Lua

Norman Ramsey-3
I felt the need for a case statement in Lua, so I added one.
Unfortunately I had to change the virtual machine as well as the
compiler, because I couldn't figure out how to duplicate the element
on top of the stack using only the existing operators.
Still, Lua is so clean that I added or changed no more than 30 lines
of code.

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
  
  print(x, y)

Some day when I have another hack attack, I'll improve the patch so
you can write multiple expressions to the left of the arrow.

This is a patch file for lua-2.5.  To build it, unpack the lua-2.5
distribution, change to the toplevel directory (called 'lua' in the
distribution), and run

  patch < this_patch_file
  (cd src; make parser)
  make

Norman Ramsey
[hidden email]


*** ./src/luac/dump.c	1997/04/13 05:24:05	1.1
--- ./src/luac/dump.c	1997/04/13 05:24:24
***************
*** 42,47 ****
--- 42,48 ----
  	case PUSH0:
  	case PUSH1:
  	case PUSH2:
+ 	case DUP:
  	case PUSHLOCAL0:
  	case PUSHLOCAL1:
  	case PUSHLOCAL2:
*** ./src/luac/print.c	1997/04/13 05:23:33	1.1
--- ./src/luac/print.c	1997/04/13 05:23:48
***************
*** 3,9 ****
  ** print bytecodes
  */
  
! char* rcs_print="$Id: print.c,v 1.11 1996/11/18 11:24:16 lhf Exp $";
  
  #include <stdio.h>
  #include <stdlib.h>
--- 3,9 ----
  ** print bytecodes
  */
  
! char* rcs_print="$Id: print.c,v 1.1 1997/04/13 05:23:33 nr Exp nr $";
  
  #include <stdio.h>
  #include <stdlib.h>
***************
*** 32,37 ****
--- 32,38 ----
  	case PUSH0:
  	case PUSH1:
  	case PUSH2:
+         case DUP:
  	case PUSHINDEXED:
  	case STOREINDEXED0:
  	case ADJUST0:
*** ./src/luac/print.h	1997/04/13 05:24:50	1.1
--- ./src/luac/print.h	1997/04/13 05:25:09
***************
*** 9,14 ****
--- 9,15 ----
   "PUSH0",
   "PUSH1",
   "PUSH2",
+  "DUP",
   "PUSHBYTE",
   "PUSHWORD",
   "PUSHFLOAT",
*** ./src/lex.c	1997/04/13 04:44:51	1.1
--- ./src/lex.c	1997/04/13 04:46:48
***************
*** 48,53 ****
--- 48,54 ----
      int token;
    } reserved [] = {
        {"and", AND},
+       {"case", CASE},
        {"do", DO},
        {"else", ELSE},
        {"elseif", ELSEIF},
***************
*** 57,62 ****
--- 58,64 ----
        {"local", LOCAL},
        {"nil", NIL},
        {"not", NOT},
+       {"of", OF},
        {"or", OR},
        {"repeat", REPEAT},
        {"return", RETURN},
***************
*** 187,194 ****
  
        case '=':
          save_and_next();
!         if (current != '=') return '=';
!         else { save_and_next(); return EQ; }
  
        case '<':
          save_and_next();
--- 189,197 ----
  
        case '=':
          save_and_next();
!         if (current == '>') { save_and_next(); return ARROW; }
!         else if (current == '=') { save_and_next(); return EQ; }
!         else return '=';
  
        case '<':
          save_and_next();
*** ./src/opcode.c	1997/04/13 05:25:23	1.1
--- ./src/opcode.c	1997/04/13 05:28:07
***************
*** 950,955 ****
--- 950,958 ----
       incr_top;
       break;
  
+    case DUP:
+      *top = *(top-1); incr_top; break;
+ 
     case PUSHBYTE: 
       tag(top) = LUA_T_NUMBER; nvalue(top) = *pc++; incr_top; break;
  
*** ./src/opcode.h	1997/04/13 05:23:02	1.1
--- ./src/opcode.h	1997/04/13 05:20:43
***************
*** 1,6 ****
  /*
  ** TeCGraf - PUC-Rio
! ** $Id: opcode.h,v 3.24 1996/11/01 12:46:59 roberto Exp $
  */
  
  #ifndef opcode_h
--- 1,6 ----
  /*
  ** TeCGraf - PUC-Rio
! ** $Id: opcode.h,v 1.1 1997/04/13 05:23:02 nr Exp nr $
  */
  
  #ifndef opcode_h
***************
*** 23,28 ****
--- 23,29 ----
  PUSH0,/*		-		0.0  */
  PUSH1,/*		-		1.0  */
  PUSH2,/*		-		2.0  */
+ DUP,/*                  x               - x x */
  PUSHBYTE,/*	b	-		(float)b  */
  PUSHWORD,/*	w	-		(float)w  */
  PUSHFLOAT,/*	f	-		f  */
*** ./src/undump.c	1997/04/13 05:48:22	1.1
--- ./src/undump.c	1997/04/13 05:29:13
***************
*** 3,9 ****
  ** load bytecodes from files
  */
  
! char* rcs_undump="$Id: undump.c,v 1.21 1996/11/18 11:18:29 lhf Exp $";
  
  #include <stdio.h>
  #include <string.h>
--- 3,9 ----
  ** load bytecodes from files
  */
  
! char* rcs_undump="$Id: undump.c,v 1.1 1997/04/13 05:48:22 nr Exp nr $";
  
  #include <stdio.h>
  #include <string.h>
***************
*** 36,41 ****
--- 36,42 ----
  	case PUSH0:
  	case PUSH1:
  	case PUSH2:
+ 	case DUP:
  	case PUSHLOCAL0:
  	case PUSHLOCAL1:
  	case PUSHLOCAL2:
*** src/lua.stx	1997/04/13 04:44:51	1.1
--- src/lua.stx	1997/04/13 05:30:26
***************
*** 426,436 ****
  
  %token WRONGTOKEN
  %token NIL
! %token IF THEN ELSE ELSEIF WHILE DO REPEAT UNTIL END
  %token RETURN
  %token LOCAL
  %token FUNCTION
  %token DOTS
  %token <vFloat> NUMBER
  %token <vWord>  STRING
  %token <pTStr>  NAME 
--- 426,437 ----
  
  %token WRONGTOKEN
  %token NIL
! %token IF THEN ELSE ELSEIF WHILE DO REPEAT UNTIL CASE OF END
  %token RETURN
  %token LOCAL
  %token FUNCTION
  %token DOTS
+ %token ARROW
  %token <vFloat> NUMBER
  %token <vWord>  STRING
  %token <pTStr>  NAME 
***************
*** 515,520 ****
--- 516,523 ----
  stat   : IF expr1 THEN PrepJump block PrepJump elsepart END
  	{ codeIf($4, $6); }
  
+        | CASE expr1 OF case_body END
+ 
         | WHILE {$<vLong>$=pc;} expr1 DO PrepJump block PrepJump END
         {
          basepc[$5] = IFFJMP;
***************
*** 553,558 ****
--- 556,569 ----
  	{ codeIf($4, $6); }
           ;
       
+ case_body : '|' {code_byte(DUP);} expr1 {code_byte(EQOP);} PrepJump ARROW 
+                 {code_byte(POP);} block PrepJump case_body
+                     { codeIf($5, $9); }
+                 /* should support multiple exprs */
+           | ELSE ARROW {code_byte(POP);} block 
+           | /* empty */ {code_byte(POP); /* should code for fallback here */ }
+           ;
+ 
  block    : {$<vInt>$ = nlocalvar;} statlist ret 
           {
  	  if (nlocalvar != $<vInt>1)

Reply | Threaded
Open this post in threaded view
|

RE: case statement for Lua

Bret Mogilefsky
Maybe it's just me, but does anyone else find this syntax, well,
gruesome?  Sorry, Norman, don't mean to offend, just expressing an
opinion.

Bret
--
"Why, that's the second biggest monkey head I've ever seen!" --Guybrush
"LeChuck's dead. I blew him into a million gooey pieces."    --Guybrush
Bret Mogilefsky   **   [hidden email]   **   Programmer, LucasArts


>----------
>From: 	Norman Ramsey[SMTP:[hidden email]]
>Sent: 	Sunday, April 13, 1997 10:45 AM
>To: 	Bret Mogilefsky
>Subject: 	case statement for Lua
>
>I felt the need for a case statement in Lua, so I added one.
>Unfortunately I had to change the virtual machine as well as the
>compiler, because I couldn't figure out how to duplicate the element
>on top of the stack using only the existing operators.
>Still, Lua is so clean that I added or changed no more than 30 lines
>of code.
>
>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
>  
>  print(x, y)
>
>Some day when I have another hack attack, I'll improve the patch so
>you can write multiple expressions to the left of the arrow.
>
>This is a patch file for lua-2.5.  To build it, unpack the lua-2.5
>distribution, change to the toplevel directory (called 'lua' in the
>distribution), and run
>
>  patch < this_patch_file
>  (cd src; make parser)
>  make
>
>Norman Ramsey
>[hidden email]
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: case statement for Lua

Lyn A Headley
>>>>> "Bret" == Bret Mogilefsky <[hidden email]> writes:

    Bret> Maybe it's just me, but does anyone else find this syntax,
    Bret> well, gruesome?  Sorry, Norman, don't mean to offend, just
    Bret> expressing an opinion.


I actually like it: reminds me of ML.

--Lyn

Reply | Threaded
Open this post in threaded view
|

Re: case statement for Lua

Norman Ramsey-3
In reply to this post by Bret Mogilefsky
 > Maybe it's just me, but does anyone else find this syntax, well,
 > gruesome?  Sorry, Norman, don't mean to offend, just expressing an
 > opinion.

It's OK -- I didn't design the syntax, so I'm not attached to it.
I borrowed from M3 because like Lua, it's Pascal-like, but with the
important difference that every control construct (if/while/case)
takes a sequence of statements with an explicit terminator, so there's
no BEGIN ... END nonsense.  The ugly | in the case statement plays the
role of the terminator for the sequence of statements in the previous
case.

The other benefit is I can point everybody to the M3 definition, and I
can blame the M3 designers for all ugliness.  Actually, the Lua
constructor syntax is nearly identical to M3 as well, ditto the if
statement. 

N

Reply | Threaded
Open this post in threaded view
|

Re: case statement for Lua

Luiz Henrique de Figueiredo-2
In reply to this post by Bret Mogilefsky
We're *not* considering adding a case statement for Lua right now, but I once
saw a syntax that seemed ok. I think it was in a toy language (or maybe it was
Turing).

CASE a + b DO             Selection is done with a case
  0 => b := b * b         statement.  The selector may be a
       END                variable or an expression.  Each
  1 => b := b + a         branch begins with 1 constant
       a := a + 1         followed by '=>' and the statements
       END                to execute.  The first branch with a
  ELSE a := a + 1         constant matching the selector is
       b := 0             executed.  An optional ELSE clause
END                       may be the last branch.  If no branch
                          matches, control passes to the
                          statement following the CASE.

If not yacc conflicts exist, I'd probably go for the simpler

CASE a + b DO
  0 : b = b * b
       END
  1 :  b = b + a
       a = a + 1
       END
  ELSE a = a + 1 
       b = 0
END

In any case (no pun intended), anyone is allowed to add statements to Lua,
*as long as they do not distribute the variant and still call it Lua*.
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: case statement for Lua

Mark Ian Barlow
In reply to this post by Bret Mogilefsky
In message <199704131744.NAA03710@...>
                                                      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.
    -----------------------------------------------------------------
    [hidden email]            Voice / Fax: +44 (0)1207 562 154

Reply | Threaded
Open this post in threaded view
|

Re: case statement for Lua

Mark Ian Barlow
In reply to this post by Norman Ramsey-3
Further to my last post, I had a little think, and you can simulate the
case implementation method I was suggesting (but without the convenient
language extension) by changing the "function" fallback as follows:

    If the object being called is a table, use the first argument to
    index it, Otherwise call the old fallback.

    If the resulting object is a function, execute it with no
    arguments and throw away any results you get.

    If the index operation fails, try the index "default", and
    proceed as above if you get a hit.

This is probably best done in 'C':

-----------------------------------------------------------------------------
void NewFunFB(void)
{
    lua_Object tbl = lua_getparam(1);
    lua_Object idx = lua_getparam(2);
    lua_Object fun;

    if (!lua_istable(tbl) || !lua_isstring(idx))  /* isstring() works for  */
        lua_call("OldFunFB");                     /* numbers too, remember */
    else
    {
        lua_pushobject(tbl);
        lua_pushobject(idx);
        fun = lua_getsubscript();
        if (lua_isfunction(fun))
            lua_callfunction(fun);
        else
        {
            lua_pushobject(tbl);
            lua_pushstring("default"); /* or whatever you want to call it */
            fun = lua_getsubscript();
            if (lua_isfunction(fun))
                lua_callfunction(fun);
            else
                lua_error("function table has no \"default\" member");
        }
    }
}
-----------------------------------------------------------------------------

Then in main() you do:

-----------------------------------------------------------------------------
lua_register("NewFunFB",NewFunFB);
lua_dostring("OldFunFB = setfallback(\"function\",NewFunFB)");
-----------------------------------------------------------------------------

You might want to do the chaining using a lua_ref, rather than with a global
name as I have here; it would be neater. You also might like to make the
default get called when lua_isnil(idx) is true, it's a debatable point.

Having done this you can write some Lua like this:

Case = {}                              -- the table that will get called

function Case:foo()     y = "abc" end  -- this is the obvious way to do it
function Case["bar"]()  y = 1     end  -- or you can do it like this
function Case[1]()      y = "xyz" end  -- wow, this works too!
Case[42] = Case[1]                     -- multiple values that call the
                                       -- same code are easy

function Case:default() y = 99    end  -- this name is just a convention,
                                       -- see the C code above.

x = "foo"  Case(x)  print(x,y)
foo
abc
x = "bar"  Case(x)  print(x,y)
bar
1
x = 1      Case(x)  print(x,y)
1
xyz
x = 42     Case(x)  print(x,y)
42
xyz
x = "baz"  Case(x)  print(x,y)
baz
99
x = 1      Case(x)  print(x,y)
1
99

Obviously, this is cracking nuts with sledgehammers, but if there were lots
more cases to cover a breakpoint would be reached beyond which it was worth
the effort. I'm betting you'ld see it round about the 10 cases mark...

Notice that in the body of the Case:foo() function the argument "self" will
be 'nil' unless you make your fallback even more sophisticated. Hmmm... can
I think of a use for that too? :-)

                        ------ *** -------

Looking at how you might go about building such a table from inside the
parser, You *would* want to allow multiple values to call the same code
(as shown in the above; it's so easy it seems a shame not to). For an
example, here's Yet Another Suggested Syntax:

case <expr> when
  <const>{,<const>} do
    <block> end
  ...
  default
    <block> end
end

To parse this you would have to either:

(a) Scan the list of constants into a temporary table, scan the associated
    code into an anonymous function body, then patch references to it into
    your jump table at each the indices held in your temporary table.

(b) Use tail recursion to scan in a constant followed by either a comma (in
    which case you recurse, then patch the returned function reference into
    the constant index) or the start of the code body, in which case you scan
    it into your anonymous function, patch the index and return a reference
    to the body.

Both sound a bit inefficient to me, so why not reverse the traditional
syntax ordering in the case branches to allow a L->R scan? here's YASS:

case <expr>
  do <block> when <const>{,<const>}
  ...
  do <block> otherwise
end

Eg:     case a+b
          do  x=1  print("yes")    when 0
          do  x=0  print("no")     when 1,2,3,4,5,6
          do  x=99 print("what?")  otherwise
        end

Is this too radical, or what? I suppose it's harder for humans to read
through the selector list when the code blocks get large, but not *much*
harder if you're careful with layout...

--  Mark Ian Barlow                Non-Linear Control Consultants Ltd.
    -----------------------------------------------------------------
    [hidden email]            Voice / Fax: +44 (0)1207 562 154

Reply | Threaded
Open this post in threaded view
|

Re: case statement for Lua

Norman Ramsey-3
In reply to this post by Mark Ian Barlow
 >  >   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.

I would be perfectly happy to use

   case x of
   when "foo" then y = 1 
                   print("x was foo")
   when "bar" then y = 2 
   else y = 99  
   end

Although I find this syntax less appealing, perhaps it is more in the
spirit of Lua.  Then again, since the Lua Masters don't want a case
statement, perhaps this discussion is moot.

 > 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. 

Agreed.  If you will read the patch carefully, you will see that it does in
fact support blocks of statements, not individual statements.  I've
modified my example above to show a block in one arm.

 > Notice the arbitrary placement of the default case; "else" looks like it
 > *has* to go at the end but "default" looks OK anywhere. 

I think it's (marginally) easier for people reading unfamiliar code to
know instantly that the default case (if any) will be last.

 > In my original post in response to LHF's "wishlist" call, asking for a case
 > construct 

Jeez, I didn't even know there was such a call---I just wanted a case
statement :-)

 > 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.

Two problems:
  - The labels on the case arms have to be compile-time constants,
    instead of arbitrary expressions.  Granted this is almost always
    the case, but I've used the alternate semantics in Icon case statements.
  - More seriously, you require Lua to implement nested functions, or
    else your anonymous functions can't change local variables.

 > This would give a real efficiency gain

I respectfully suggest that we not consider efficiency until we have
measurements of at least one Lua program showing that sequentially
evaluated case statements are a performance bottleneck.

N

Reply | Threaded
Open this post in threaded view
|

Re: case statement for Lua

Steve Dekorte
In reply to this post by Norman Ramsey-3
>Maybe it's just me, but does anyone else find this syntax, well,
>gruesome?

Anyone considered giving Lua a Smalltalk/Objective-C like syntax?

This is what Objective-C looks like:

- addAttributeNamed:aName withValue:aString
{
   id newAttribute = [[Attribute alloc] init];
   [newAttribute setItemName:aName];
   [newAttribute setValue:aString];
   [attributeList addObject:newAttribute];
   return self;
}

---
Steve Dekorte - OPENSTEP developer - San Francisco

Reply | Threaded
Open this post in threaded view
|

Re: case statement for Lua

David Jeske
In reply to this post by Mark Ian Barlow
On Apr 14, [hidden email] (Mark Ian Barlow) wrote:
> 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

I agree 100%. This seems to fit better into the kind of syntax lua
promotes. 

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

My first thought was that "caseof x" (or "caseof x :" to have a
terminating characer) would make sense. However, I like "with x
choose" it seems more readable to me (i.e. for non-programmer types
especially)

> 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.

I had the same thought, except that if it really was implemented as
anonymous functions, local variable scope would be confused would it
not? (Just starting to use Lua, so correct me if this is wrong)

> 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...

agreed 100%. 

-- 
David Jeske (N9LCA)   +   [hidden email]   +   http://www.igcom.net/~jeske/

Reply | Threaded
Open this post in threaded view
|

Re: case statement for Lua

Mark Ian Barlow
In reply to this post by Norman Ramsey-3
Fair enough, Norman; my simulation of a hashed case construct only works
at global scope because nested functions are illegal. What I really want
is to have a table of *blocks*. Perhaps I can hack a better example with
Lua 3.0alpha's new userdata type... I'm just about to download it.

Meanwhile I'll look into benchmarking the global-only version for different
sized case lists. I'll post anything interesting I find out. As LHF said
we won't be getting a case construct just yet this is a bit academic I
suppose, but what the heck...

--  Mark Ian Barlow                Non-Linear Control Consultants Ltd.
    -----------------------------------------------------------------
    [hidden email]            Voice / Fax: +44 (0)1207 562 154

Reply | Threaded
Open this post in threaded view
|

Re: case statement for Lua

David Jeske
On Apr 14, [hidden email] (Mark Ian Barlow) wrote:
> Fair enough, Norman; my simulation of a hashed case construct only works
> at global scope because nested functions are illegal. What I really want
> is to have a table of *blocks*. Perhaps I can hack a better example with
> Lua 3.0alpha's new userdata type... I'm just about to download it.

It would be nice (IMO) to be able to declare blocks _and_ anonymous
functions inline. I would like to be able to do the following:

a_location = { x = 0, y = 0
swap = function(self) 
   self.x,self.y = self.y,self.x;
end ,
dup = function(self)
   self.x = self.y;
end
}

Or the equivilant. (I don't care about the syntax). Right now, if you
want to setup an "object" out of a table which has data and methods,
you have to do it separately (again, please correct me if this is wrong):

a_location = { x = 0, y = 0}
function a_location:swap()
   self.x,self.y = self.y,self.x;
end
function a_location:dup()
    self.x = self.y
end


> Meanwhile I'll look into benchmarking the global-only version for different
> sized case lists. I'll post anything interesting I find out. As LHF said
> we won't be getting a case construct just yet this is a bit academic I
> suppose, but what the heck...

I think this should yeild some interesting results.

-- 
David Jeske (N9LCA)   +   [hidden email]   +   http://www.igcom.net/~jeske/