Lua 语言中 switch 语句的替代方案是什么?

问题描述 投票:0回答:10

我有这段C++代码,我想知道如何编写一些代码来替换Lua中的switch语句,因为我面临很多问题并且我需要使用这个语句。

int choice;
do // loop
{
    cout<<"\n >>> The General Menu <<< \n";
    cout << endl;
    cout<< " press (1) to Add    "<<endl;
    cout<< " press (2) to Save   "<<endl;
    cout<< " press (3) to Quit " << endl;
    cout<< endl;
    cout<< "Enter your choice please (1/2/3): ";
    cin>>choice;

    switch(choice)
    {
        case 1: 
            add();
            break;
        case 2:
            save();
            break;
            
        default:
            cout<<" The program has been terminated "<<endl;
            cout<<" Thank you! \n";         
    }   
} while (choice != 3);

该语句已在 do..while 循环中使用。

lua switch-statement
10个回答
26
投票

一般来说,如果你想要在Lua中使用switch语句,你应该做的就是建一个表。对于

choice
的简单情况(可能是 1、2 或失败),带有一些条件的简单
if
语句就足够了。对于更复杂的情况,应使用函数表:

local c_tbl =
{
  [1] = add,
  [2] = save,
}

local func = c_tbl[choice]
if(func) then
  func()
else
  print " The program has been terminated."
  print " Thank you!";
end

您可以使用词法作用域来允许表中的函数能够访问局部变量,就像代码是内联编写的一样。


10
投票

尝试这个(单击此处在 Lua 编译器中运行脚本),希望代码是不言自明的;-) 和

类似于相同的伪代码格式..!!

print("enter your choice : ")
mychoice = io.read()

switch = function (choice)
  -- accepts both number as well as string
  choice = choice and tonumber(choice) or choice     -- returns a number if the choic is a number or string. 

  -- Define your cases
  case =
   {
     [1] = function ( )                              -- case 1 : 
             print("your choice is Number 1 ")       -- code block
     end,                                            -- break statement

     add = function ( )                              -- case 'add' : 
             print("your choice is string add ")     -- code block
     end,                                            -- break statement

    ['+'] = function ( )                             -- case '+' : 
             print("your choice is char + ")         -- code block
     end,                                            -- break statement

     default = function ( )                          -- default case
             print(" your choice is din't match any of those specified cases")   
     end,                                            -- u cant exclude end hear :-P
   }

  -- execution section
  if case[choice] then
     case[choice]()
  else
     case["default"]()
  end

end
-- Now you can use it as a regular function. Tadaaa..!!
switch(mychoice)

6
投票

卢阿:

if choice == 1
then add()
elseif choice == 2
then save()
else print "The program has been terminated\nThank you!"
end 

1
投票

切换器的另一个版本(无需将表初始化为变量):

local case=2;
local result=({[1]="case1", [2]="case2", 3="case3"})[case];
print (result); --> case2

1
投票

虽然简单地创建一个按案例索引并以函数作为元素的表很可能是最快的方法,但我提出了一个解决方案,IMO 具有更好的代码可读性:

function switch(element)
  local Table = {
    ["Value"] = element,
    ["DefaultFunction"] = nil,
    ["Functions"] = {}
  }
  
  Table.case = function(testElement, callback)
    Table.Functions[testElement] = callback
    return Table
  end
  
  Table.default = function(callback)
    Table.DefaultFunction = callback
    return Table
  end
  
  Table.process = function()
    local Case = Table.Functions[Table.Value]
    if Case then
      Case()
    elseif Table.DefaultFunction then
      Table.DefaultFunction()
    end
  end
  
  return Table
end

使用示例:

switch(Player:GetName())
  .case("Kate", function() print("This player's name rhymes with Fate")end)
  .case("Tod", function() print("This player's name rhymes with Cod") end)
  .default(function() print("This player's name is not Kate or Tod") end)
  .process()

1
投票

我遇到了这个问题,函数需要不同的参数 - 其他答案不能很好地处理这个问题。
我用匿名函数解决了这个问题。

-- call the relevant execution based on its opcode
local instructions = {
    [01] = function () self:perform_add(table.unpack(valargs)) end,
    [02] = function () self:perform_multiply(table.unpack(valargs)) end,
    [03] = function () self:perform_store_input(outputargs[1]) end,
    [04] = function () self:perform_output(valargs[1]) end,
    [05] = function () self:perform_jnz(table.unpack(valargs)) end,
    [06] = function () self:perform_jz(table.unpack(valargs)) end,
    [07] = function () self:perform_less_than(table.unpack(valargs)) end,
    [08] = function () self:perform_equals(table.unpack(valargs)) end,
    [99] = function () self:perform_exit() end,
}
local instr = instructions[opcode]
if (instr) then
    instr()
else
    print("No instruction for opcode " .. opcode)
end

我想要在不同的 switch 情况下执行的操作都被定义为表中的匿名函数。使用的键(例如此处的

08
)是我们要打开的变量可能假设的值(此处的
opcode
)。 switch 语句的默认情况发生在我的
else
子句中。不需要
break
等效项 - 但如果您想让一个案例继续下一个案例,您必须显式调用它。


回复要求澄清的评论:

你说得对,这个例子并不完整。你可以在这里找到我在2019年第7天进行adventofcode时的用法。我可以尝试回答你的问题,但我之前从未接触过lua,之后也从未接触过。

valargs
是一个参数表,因为这里不同的函数采用不同数量的参数。但这不一定与问题相关。基本上,我只是在这里调用函数。

在我的示例中,

self
存在,因为我在
local
上定义了函数(并做了一些奇怪的更改,如here所述)。相关代码部分:

-- a "class"
local IntComputer = {}

    function IntComputer:perform_exit()
        self.program_ended = true
    end

    function IntComputer:perform_add(a, b, target)
        print("    " .. a .. " + " .. b .. " => " .. target)
        self:set_value(target, a+b)
    end

0
投票

如果您希望 switch 作为可调用的函数,您可以使用一些有趣的回调功能:

(下面的示例是基于变量类型的 switch 语句,但是您可以将表索引设置为您想要测试的任何内容。只需将 switch 函数的 return 语句更改为不测试类型(case))

(这本质上是一个惰性表查找,很像Python的字典功能,但每个元素都是一个函数)

#!/usr/bin/lua
-- Callback switch statement:
local function switch(a, case)
  -- Local variable instead of function(a) on every case:
  local value = a
  -- Cases list:
  local switchcase = {}

  -- Cases:
  switchcase["string"] = function()
    return (tostring(value) .. " is a string")
  end

  switchcase["number"] = function()
    return tostring(value .. " is a number")
  end

  switchcase["boolean"] = function()
    return (tostring(avalue) .. " is a boolean")
  end

  return switchcase[type(case)](a)
end

local value = 5
print(switch(value,value)) --> 5 is a number

local value = "test"
print(switch(value,value)) --> test is a string

local value = true
print(switch(value,value)) --> true is a boolean

我不知道这段代码与上面给出的两个答案相比的性能,但使用局部变量应该使它足够快以供重复使用。如果您在全局范围内创建 switch 函数,它可能会成为您的项目使用的标准函数。


0
投票

这是另一个有趣的方法,使用 loadstring() 和表查找。

switch = function(cases,args)
  if (cases[args] == nil) then return args else return assert(loadstring ('return ' .. cases[args]))() end
end

local case = 2

local result = switch({
  [1] = "2^" .. case,
  [2] = string.format("2^%i",case),
  [3] = tostring(2^case)
},
case
)
print(result) --> 4

此方法使用起来有些危险,因为 loadstring() 类似于 Python 的 eval() 函数。

我发现在 Lua wiki 提供的示例中的每个案例上都写“function(x)”是很丑陋的。这是一个巧妙的方法。

“默认”情况是函数的“返回参数”部分。


0
投票

我使用这个代码:

while true do local tmpswitch1 = exp ; --[[ switch <exp> do ]]
    if tmpswitch1 == exp1 then --[[ case <exp1> : ]]
        -- do something
        break
    end ;if tmpswitch1 == exp2 then --[[ case <exp2> : ]]
        -- do something
        break
    end ; --[[ default : ]]
        -- do something
break ; end --[[ switch tmpswitch1 ]]

-1
投票
function case(i,d) return function(t) return t[i] or d end end

x='two'

r=case(x) {
 one=1,
 two=2,
 three=3,
}

case(r,function() print "default" end) {
  [1]=function() print "one" end,
  [2]=function() print "two" end,
  [3]=function() print "three" end,
}()
© www.soinside.com 2019 - 2024. All rights reserved.