是否有更有效的方法来编写if(或)语句?

时间:2017-05-14 15:51:24

标签: lua

我希望确保在Lua中更有效地编写此语句是不可能的:

if (value == 1 or value == 2) then

这样的例子(我假设不工作):

if (value == (1 or 2)) then

if value == (1;2) then

1 个答案:

答案 0 :(得分:4)

让我们看一下生成的字节码作为速度的代理。 (微观标记可靠。缓存,管道连接,分支预测......可以有真正奇怪的效果,可以使应该的代码原则上更慢在实际使用它的环境中实践中表现更好。字节码大小也不是一个很好的指标(同样的问题适用),但至少它很容易生成,确定性和简单解释。)

(顺便说一句,将测试文件放在luac -p -l,这只会p屁股(不会编写已编译的文件)而l将得到的字节码作为副作用如果您想了解字节码,请查看最初由Kein-Hong Man创建的unofficial bytecode reference,并由Dibyendu Majumdar亲自更新。但您不必这样做。)

如果value是一个全局变量,你会得到这个:

1   [1] GETTABUP   0 0 -1 ; _ENV "value"
2   [1] EQ         1 0 -2 ; - 1   (fall through to next comparison)
3   [1] JMP        0 3    ; to 7  (true branch)
4   [1] GETTABUP   0 0 -1 ; _ENV "value"
5   [1] EQ         0 0 -3 ; - 2   (fall through into true branch)
6   [1] JMP        0 1    ; to 8  (beyond true branch)

转换回“伪Lua”,这是粗鲁的

local r0 = _ENV["value"]
if r0 == 1 then  goto true_branch  end
local r0 = _ENV["value"]
if r0 ~= 2 then  goto fin  end
::true_branch::
-- stuff here
::fin::

如果你使用它的函数中valuelocal(或函数参数),那么你会得到类似的东西:

1   [1] EQ         1 0 -1 ; - 1
2   [1] JMP        0 2    ; to 5
3   [1] EQ         0 0 -2 ; - 2
4   [1] JMP        0 1    ; to 6

或粗略

if r0 == 1 then  goto true_branch  end
if r0 ~= 2 then  goto fin  end
::true_branch::
-- stuff here
::fin::

“好多了”!

因此,如果value是全局变量(或upvalue),则执行

local value = value
if value == 1 or value == 2 then
  -- stuff
end

会给你

1   [1] GETTABUP   0 0 -1 ; _ENV "value"
2   [1] EQ         1 0 -2 ; - 1
3   [1] JMP        0 2    ; to 6
4   [1] EQ         0 0 -3 ; - 2
5   [1] JMP        0 1    ; to 7

local r0 = _ENV["value"]
if r0 == 1 then  goto true_branch  end
if r0 == 2 then  goto true_branch  end
goto fin
::true_branch::
-- stuff here
::fin::

保存一次查找。 (虽然微基准测试会显示出明显的差异,在实践中你几乎从未注意到差异。如果你正在进行更深入的查找if foo.bar.baz == 1 or foo.bar.baz == 2 then,首先local是有意义的,它可能也会增加可读性。)