Lua中的三元运算符(function)

我在codewars中遇到了这样的问题:

实现一个函数,根据布尔值运行2个不同的函数。当然,可以使用简单的if语句来实现。就像这样:

function _if(bool, func1, func2)
    if bool then return func1() else return func2() end
end

然而,当我想用三元运算符解决它时,它并没有通过所有的测试用例:

function _if(bool, func1, func2)
    return bool and func1() or func2()
end

但这个可以:

function _if(bool, func1, func2)
    return (bool and func1 or func2)()
end

我想我对Lua的知识还不够。我已经在社区中搜索了这个问题,但没有找到任何明确的解释。我想知道有人是否能为我解惑或者提供一些可能帮助我理解的文章。

更新编辑

好吧,那么如果func1总是返回真值,第二个段落与第三个段落有什么区别呢?

点赞
用户3735873
用户3735873

if 的版本不等同于用 and 的第二个版本

如果 func1() 返回 false,则会评估 or 部分并返回 func2() 的结果。

最后一个版本可以工作(当 func1 不为 nil 时)因为你调用函数时已经确定了要调用哪个函数。因此,bool 只是选择要调用下一个函数的 '指针'。假设 func1 不为空,指针将永远不会为 false。

2017-10-23 09:20:39
用户2328287
用户2328287

你的代码存在几个潜在问题:

  1. 如上所述,如果 func1 返回任何 falsy 值,则会调用 func2
  2. bool and func1() or func2() 只返回一个结果。
2017-10-23 09:20:48
用户2858170
用户2858170

以下代码将返回 func1() 如果 bool 为 true,否则返回 func2()。

function _if(bool, func1, func2)
    if bool then return func1() else return func2() end
end

以下代码将在 bool 不为 true 或者 bool 为 true 但 func1() 不为 true 时返回 func2()。只有当 boolfunc1() 都为 true 时,才会返回 func1()

function _if(bool, func1, func2)
    return bool and func1() or func2()
end

最后一段代码将在 bool 为 true 时返回 func1(),否则返回 func2()

function _if(bool, func1, func2)
    return (bool and func1 or func2)()
end

首先,Lua 没有三目运算符。利用 and 的优先级高于 or 的巧妙使用与 C 的 ?: 运算符是等价的。

其次,如果将函数调用作为 c,则表达式 a = b and c or d 只会在 c 为 true 时才能正常工作,否则可能会出现问题。

虽然这种方式对于赋值来说很方便,但在许多情况下,仅使用 if-else 语句可以增加可读性并减少错误。

一旦需要添加更多条件,使用 andor 的技巧就会变得非常混乱。

因此,让我们再看看第二个代码片段中发生了什么。

function _if(bool, func1, func2)
    return bool and func1() or func2()
end

首先,将计算 boolfunc1()。如果 bool 不为 true,则 Lua 不必调用 func1(),因为表达式永远不可能为 true。因此,Lua 可以立即去评估 func2()。你的函数将返回 func2()!

相反,如果 bool 为 true,则 Lua 将调用 func1() 来查看它是否为 true。如果 func1() 返回 true,则 Lua 将不会调用 func2()。由于以下 or,如果 boolfunc1() 为 true,则表达式始终为 true。如果 func1() 返回 false/nil,则必须评估 or。因此,Lua 也会调用 func2(),然后返回它的返回值。

重要的是要知道运算符优先级及在哪些情况下 Lua 将中止评估表达式!

Lua 的 orand 运算符使用短路评估。仅在必要时才计算第二个操作数。

2017-10-23 09:39:41
用户5287638
用户5287638

或许通过只使用 or 运算符,你可以更好地理解其工作原理。

function func1()
    return true
end

function func2()
    return false
end

print(func1() or "default") -- true
print(func1 or "default")   -- function: 0x2377c80
print(func2() or "default") -- default
print(func2 or "default")   -- function: 0x2377cb0

如果在 func1func2 两个函数后不加括号,会返回一个函数对象。而在 Lua 中,函数对象总是被视为真值(只有 falsenil 才会被视为假值)。

2017-10-23 23:53:13