switch statement

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

switch statement

Supratik Champati
Hi Everyone,
How hard is it to add a switch statement to lua. Currently I am
using if then elseif statements - switch case statements would
be more efficient and also more readable.
Thanx.

Supratik

Reply | Threaded
Open this post in threaded view
|

Re: switch statement

Norman Ramsey-3
 > How hard is it to add a switch statement to lua. Currently I am
 > using if then elseif statements - switch case statements would
 > be more efficient and also more readable.

It's pretty easy --- I posted patches to this list a year or two ago,
but they are for Lua 2.5.  The results are much more readable but not
more efficient---because I wanted to switch on arbitrary values,
especially strings, the switches are implemented much as a sequence of
if-then-elses.

Norman

Reply | Threaded
Open this post in threaded view
|

Re: switch statement

Luiz Henrique de Figueiredo
In reply to this post by Supratik Champati
>From: Supratik Champati <[hidden email]>
>
>How hard is it to add a switch statement to lua.

not too hard, but we don't think it's worth it, because we would do it in
full generality and not for numbers only. so, in the end, it would be very much
like a chain of if-then-elseif statements.

Norman Ramsey has modified Lua to include a case statement.
However, as far as I know, he used Lua 2.5 and hasn't moved to 3.1.

>using if then elseif statements - switch case statements would
>be more efficient and also more readable.

I agree with readbility, but not with efficiency. Remember that you're using
an interpreted language, which is already "slow" (however, Lua is said to be
one of the fastest extension languages around).

The "efficient" way in Lua is to *index* a table of functions. something like:

 action={
	 [1] = function (x) B1 end,
	 [2] = function (x) B2 end,
	 ["nop"] = function (x) B3 end,
	 ["my name"] = function (x) B4 end,
 }

then do

 action[x](x)

instead of

 switch (x)
 case 1: B1
 case 2: B2
 case "nop": B3
 case "my name": B4
 end

Not that the action table is more readable...
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: switch statement

Michael T. Richter
> The "efficient" way in Lua is to *index* a table of functions. something
> like:

[snip]

That is a really cute idiom.  That's a keeper.

-- 
Michael T. Richter    <[hidden email]>    http://www.igs.net/~mtr/
          PGP Key: http://www.igs.net/~mtr/pgp-key.html
PGP Fingerprint: 40D1 33E0 F70B 6BB5 8353 4669 B4CC DD09 04ED 4FE8

Reply | Threaded
Open this post in threaded view
|

Re: switch statement

David Jeske-2
In reply to this post by Luiz Henrique de Figueiredo
On Mon, Dec 07, 1998 at 02:36:34PM -0200, Luiz Henrique de Figueiredo wrote:
> The "efficient" way in Lua is to *index* a table of
> functions. something like:

I've always thought it would be nice to be able to imbed context-less
code-blocks. Sort of like a run-time evaluated macro which would
execute in the context it was called from. This would allow the
table-driven-switch to operate without requiring you to pass in any
variables you wanted access to.

>  action={
> 	 [1] = function (x) B1 end,
> 	 [2] = function (x) B2 end,
> 	 ["nop"] = function (x) B3 end,
> 	 ["my name"] = function (x) B4 end,
>  }

With a little trickery, you can make this even cooler...

 Switch{
   [1] = function (x) B1 end,
   [2] = function (x) B2 end,
   ["nop"] = function (x) B3 end,
   ["my name"] = function (x) B4 end,
   ["__default__"] = function (x) B5 end
 }[x](arg);

Where the 'Switch' function sets the tag of the table so unknown
accesses return the "__default__" element.

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

Reply | Threaded
Open this post in threaded view
|

Re: switch statement

David Jeske-2
On Mon, Dec 07, 1998 at 09:35:13PM -0200, David Jeske wrote:
> With a little trickery, you can make this even cooler...
> 
>  Switch{
>    [1] = function (x) B1 end,
>    [2] = function (x) B2 end,
>    ["nop"] = function (x) B3 end,
>    ["my name"] = function (x) B4 end,
>    ["__default__"] = function (x) B5 end
>  }[x](arg);
> 
> Where the 'Switch' function sets the tag of the table so unknown
> accesses return the "__default__" element.

Or you could put the switchvar and arguments up at the top:

Switch(switch_var,{arg1, arg2}, {
    [1] = function (x) B1 end,
    [2] = function (x) B2 end,
    ["nop"] = function (x) B3 end,
    ["my name"] = function (x) B4 end,
    ["__default__"] = function (x) B5 end
});

function Switch(sw_var, args, swtbl)
    local val;

    val = swtbl[sw_var]

    if (not val) then
       val = swtbl["__default__"];
       if (not val) then
            lua_error(format("Missing case in switch ("..
               tostring(sw_var)..")"));
       end
    end

    if (type(val) ~= "function") then
       if (not args) then
          return val; -- passive switch
       else
          lua_error(format("Non function case in switch ("..
              tostring(sw_var)..")"));
       end
    end

    return call(val,args); -- I think this is the right syntax for call()
end

======

I have a question for the Lua implementors though. What are the
performance implications of putting this table initialization syntax
within a function call? What is the overhead of putting the above example in a function vs doing it like this:

switch_tbl = {
    [1] = function (x) B1 end,
    [2] = function (x) B2 end,
    ["nop"] = function (x) B3 end,
    ["my name"] = function (x) B4 end,
    ["__default__"] = function (x) B5 end
};

function a()
   Switch(switch_var,{arg1,arg2},switch_tbl);
end




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

Reply | Threaded
Open this post in threaded view
|

Re: switch statement

Supratik Champati
In reply to this post by Luiz Henrique de Figueiredo
> The "efficient" way in Lua is to *index* a table of functions. something like:
> 
>  action={
>          [1] = function (x) B1 end,
>          [2] = function (x) B2 end,
>          ["nop"] = function (x) B3 end,
>          ["my name"] = function (x) B4 end,
>  }
> 
> then do
> 
>  action[x](x)

The above solution will actually work fine for me.
Thanks a lot.

Also I was wondering if someone has already written (and would
graciously like to share)
some kind of lua add-on that would enable us to dynamically load object
files.
The reason I need this is that some functions are too time consuming to
be implemented
in lua hence it would be nice to be able to write them in c/c++ and
somehow make the
compiled object "dynamically" visible to lua.

Reply | Threaded
Open this post in threaded view
|

Re: switch statement

Luiz Henrique de Figueiredo
In reply to this post by Supratik Champati
>From: David Jeske <[hidden email]>
>
>I have a question for the Lua implementors though. What are the
>performance implications of putting this table initialization syntax
>within a function call? What is the overhead of putting the above example in a function vs doing it like this:
>
>switch_tbl = {
>    [1] = function (x) B1 end,
>    [2] = function (x) B2 end,
>    ["nop"] = function (x) B3 end,
>    ["my name"] = function (x) B4 end,
>    ["__default__"] = function (x) B5 end
>};
>
>function a()
>   Switch(switch_var,{arg1,arg2},switch_tbl);
>end

I'm not sure what you mean here.
If you want to know whether there is any overhead in defining "local" functions,
then the answer is no: functions are always compiled just once, even if they
contain upvalues.

On the other hand, if a table is going to be used very frequently, then it's
faster to save it in a variable. In other words:

  i=0
  while i<1000 do
	  f{a=1,b=2,c=3,...}	-- long table
	  i=i+1
  end

is "slower" than 

  do
  local t={a=1,b=2,c=3,...}	-- long table
  i=0
  while i<1000 do
	  f(t)
	  i=i+1
  end
  end

If t is slighty different for each i (otherwise, what's the point), then
it's still better to use the second form and just change the new fields:

  do
  local t={a=1,b=2,c=3,...}	-- long table
  i=0
  while i<1000 do
	  t.i=i
	  f(t)
	  i=i+1
  end
  end

Now, as I have been pointing out lately, "slow" and "fast" are very relative.
As a programmer, I also feel this urge to make everything fast, but you have
to keep in mind that the loop overhead (i<1000, i=i+1) is probably comparable
to anything else.
So, I'd go for the more readable code, whatever it is.
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: switch statement

Luiz Henrique de Figueiredo
In reply to this post by Supratik Champati
Here is a nicer implementation:

 function switch(t)
  t.case=function (self,x)
		 local f=self[x] or self.default
		 if f then
			 if type(f)=="function" then
				 f(x,self)
			 else
				 error("case "..tostring(x).." not a function")
			 end
		 end
  end
  return t
 end

  a=switch{
  [1]=function (x) print(x,10) end,
  [2]=function (x) print(x,20) end,
  default=function (x) print(x,0) end,
  }

 a:case(2)
 a:case(9)

--lhf