lua-users home
lua-l archive

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


On Jun 11, 2014, at 9:13 PM, Ross Bencina <rossb-lists@audiomulch.com> wrote:

> On 12/06/2014 10:44 AM, Paige DePol wrote:
>> Perhaps you could elaborate on this point a bit as I feel I am
>> missing something here. Under C switch statements require literal
>> values yet switch statements are widely used and, as far as I know,
>> the use of which is not considered bad code.
> 
> Hopefully I'm not putting words into Roberto's mouth here. In any case it's not my intention. My impression is as follows:
> 
> In C there are two mechanisms for symbolic constants: #defines and enums.
> 
> A switch like this:
> 
> switch(x){
> 	case 3: foo(); break;
> 	case 42: bar(); break;
> 	case 66: baz(); break;
> };
> 
> Would be considered bad style. The following (using enum or #defined constants) would not:
> 
> switch(x){
> 	case MOUSE_UP: foo(); break;
> 	case MOUSE_DOWN: bar(); break;
> 	case MOUSE_MOVE: baz(); break;
> }
> 
> The problem is in Lua (unless I'm missing something), you don't have symbolic constants, so it's not possible to "compile" the second form to anything better than a sequence of comparisons. If you use Lua variables, their values are not constant, and so could change each time the switch is executed (hence the equivalence to a linear if/else chain).

Ah, okay, we are talking about magic numbers essentially. Though the #defines are just pre-processed into their values before compilation takes place, so the use of MOUSE_UP is only just for the programmer, the compiler would just see `3` (assuming 3, 42, and 66 map to MOUSE_UP, _DOWN, and _MOVE in your example).


>> In which way does adding symbolic constants allow the optimising of
>> switch statements?
> 
> It allows for a balanced tree, perfect hash and/or static lookup table to be constructed at compile time. This can also be done if the cases are numeric or string literals (perhaps that's what your patch does, sorry I haven't looked at it). But it can not be done if the cases are symbolic (because the values can change), which I would suggest is by far the most common use-case (maybe you have others though).

Yes, in my case all case values are placed into a Lua table, then when the switch is encountered a single table lookup is done on the value given, if a value is present in the table then that is used as the jump offset to use. I guess in my programming experiences most uses of a switch-like statement have required constant case values, which is what my patch also requires.


>> How would adding a switch optimised for literals
>> badly impact the code standards for Lua?
> 
> By people writing code as in my first example above.

Which is not just a problem for Lua, but for any programming language. However, this is not really a failing of switch statements, but rather not having a facility to allow declaration of constants to avoid the use of magic numbers.

Actually, I am just finishing off another patch for Lua that adds a new feature which in turn allows the use of three new keywords: const, macro, and inline. Details will be posted as soon as I've written up the documentation... which will be when the gout in my wrist subsides! :(


>> Obviously, as I have created a switch patch for Lua (based on
>> computed gotos) I have an interest in understanding the points being
>> raised here! ;)
> 
> For the record: I started writing my earlier email to defend the utility of a computed goto, and then realized what Roberto was talking about.
> 
> Maybe your patch has a solution that resolves the above.
> 
> Ross.

My switch-case (computed goto) patch, by itself, does not solve the issue above. Actually, so far as I can tell the issue we are talking about is really a problem with Lua not having a way to declare constant values. The same issue exists for if/elseif blocks as well:

if (x == 3) then
    foo()
else if (x == 42) then
    bar()
else if (x == 66) then
    baz()
end


With my switch patch[1] the above can be written as follows:

switch and break on x
    case 3
        foo()
    case 42
        bar()
    case 66
        baz()
end


With my newest patch, which allows creation of constants, the above code could be written as follows, which is a lot more readable:

const MOUSE_UP     3
const MOUSE_DOWN  42
const MOUSE_MOVE  66

switch and break on x
    case MOUSE_UP
        foo()
    case MOUSE_DOWN
        bar()
    case MOUSE_MOVE
        baz()
end


The same constants could be applied to the if/elseif block above as well to increase readability.

Actually, I am not sure how the computed goto has the same failings, essentially the computed goto is using the value of a variable to do a table lookup, if the value is present then perform a jump, if not do some error handling. With a computed goto you are not jumping to a known-at-compile-time value, but rather a computed value at run-time, which is very different than the standard goto which uses static labels and to which jumps are resolved at compile time.

Thank you for your post, I do believe I understand what was meant by the prior post. Though I do wonder if I am still missing something as it seems the problem that exists is more related to the lack of constant declaration than the syntax of switch statements.

~pmd

[1] https://github.com/FizzyPop/lua-patches/tree/master/joint-patches/jump-table%2Bif-shct%2Bcont-loop