-
-
Save FreeBirdLjj/6303864 to your computer and use it in GitHub Desktop.
print "Hello, switch" | |
-- If the default case does not have to be handled, we can use the following auxiliary function: | |
local function switch(value) | |
-- Handing `cases` to the returned function allows the `switch()` function to be used with a syntax closer to c code (see the example below). | |
-- This is because lua allows the parentheses around a table type argument to be omitted if it is the only argument. | |
return function(cases) | |
-- The default case is achieved through the metatable mechanism of lua tables (the `__index` operation). | |
setmetatable(cases, cases) | |
local f = cases[value] | |
if f then | |
f() | |
end | |
end | |
end | |
-- Suppose we want to write the equivalent lua code of the following c code: | |
-- switch (a) { | |
-- case 1: | |
-- printf("Case 1.\n"); | |
-- break; | |
-- case 2: | |
-- printf("Case 2.\n"); | |
-- break; | |
-- case 3: | |
-- printf("Case 3.\n"); | |
-- break; | |
-- default: | |
-- printf("Case default.\n"); | |
-- } | |
local x = 2 | |
switch (x) { | |
[1] = function() -- for case 1 | |
print "Case 1." | |
end, | |
[2] = function() -- for case 2 | |
print "Case 2." | |
end, | |
[3] = function() -- for case 3 | |
print "Case 3." | |
end, | |
__index = function() -- for case default, can be omitted if not needed | |
print "Case default." | |
end | |
} |
Thank you.
@switch.lua Thank you.
The small problem with this technique is that it cannot mimic case-fall-through
so for example, one cannot easily port following C code
switch (a) {
case 1:
printf("Case 1.\n");
break;
case 2:
case 3:
default:
printf("Case 2, 3 or default.\n");
}
I don't think there is any sane and simple solution in said case
Hi @sleeptightAnsiC, I guess you can try the following code as a solution:
local function fallthrough(next_case)
coroutine.yield("fallthrough", next_case)
end
local function switch(value)
return function(cases)
setmetatable(cases, cases)
repeat
local f = cases[value]
if f then
local act, next_case = coroutine.wrap(f)()
if act == "fallthrough" then
value = next_case
else
break
end
end
until f == nil
end
end
-- Suppose we want to write the equivalent lua code of the following c code:
-- switch (a) {
-- case 1:
-- printf("Case 1.\n");
-- break;
-- case 2:
-- case 3:
-- default:
-- printf("Case 2, 3 or default.\n");
-- }
for _, v in ipairs {1, 2, 3, 4} do
switch (v) {
[1] = function()
print "Case 1."
end,
[2] = function() fallthrough(3) end,
[3] = function() fallthrough(0 --[[ any default value ]]) end,
__index = function() -- for case default
print "Case 2, 3 or default."
end
}
end
Hey @FreeBirdLjj,
Gosh... Lua shocks me everyday with its meta-programming capabilities. This indeed works.
I wonder about performance penalty of said approach as it uses coroutine
?
Using fallthrough here kinda skyrockets the complexity, since every falling case N
must explicitly call fallthrough N+1
and adding/removing cases becomes complicated, so not sure if this is a great solution. Maybe something like this [code bellow] would be better in a long run.
-- `switch` is defined in a same way as in the first example
local case_1 = function ()
print "Case 1."
end
local case_23d = function()
print "Case 2, 3 or default."
end
for _, x in ipairs {1, 2, 3, 4} do
switch (x) {
[1] = case_1,
[2] = case_23d,
[3] = case_23d,
__index = case_23d,
}
end
Thanks for your answer though, I haven't thought this would be even possible.
Also, I just realized that I use a simple Lua idiom that basically works like switch-case (not exactly, but it's very similar). I'll leave it there, I hope someone may find it useful:
print "Hello, switch"
local x = 2
local result =
x == 1 and "Case 1."
or x == 2 and "Case 2."
or x == 3 and "Case 3."
or "Case default."
print(result)
This removes the need of using metatable entirely.
Also, I just realized that I use a simple Lua idiom that basically works like switch-case (not exactly, but it's very similar). I'll leave it there, I hope someone may find it useful:
print "Hello, switch" local x = 2 local result = x == 1 and "Case 1." or x == 2 and "Case 2." or x == 3 and "Case 3." or "Case default." print(result)This removes the need of using metatable entirely.
The benefits of using switch-case over if-elif-else is to not repeat the x
variable... otherwise there is no point, like in your example.
Awesome, thanks