熟悉 C/C++ 的老司机都知道三目运算 a ? b : c,这种写法替换简单的条件判断语句可以在不增加阅读难度的情况下,使代码尽量保持简洁。
int a, b, ret;
//if-else
if (a > b)
ret = a;
else
ret = b;
//三目运算符
ret = a > b ? a : b;
Lua 原生的语义并没有实现三目运算,一般是通过逻辑运算符 and 和 or 来模拟三目运算符的。
Lua 中 and 和 or 都使用"短路求值(short_cur evaluation)",也就是说,它们只会在需要时才去评估第二个操作数。(《Lua程序设计》)
local a, b, ret;
ret = a > b and a or b
穷举所有可能性:
a > b 时:
a > b and a –> true
a or b –> a
a <= b时:
a > b and a –> false
a or b –> b
完美!
按照从特殊到一般的原则:
三目运算的一般形式a ? b : c
a = true,结果为b
a = false,结果为c
对应Lua中的a and b or c
可以看到当 b = false 时,Lua模拟的 a and b or c 始终返回 c 并不能还原三目运算符的原貌。
《Lua程序设计》也建议这种情况使用 if-else 来避免。
那么有没有办法可以解决 b = false 失效的问题呢?
由此我联想到 C 语言有一道常规的考题:请使用宏定义写一个返回两个值中较小值的方法。
在校时第一次看到本题,第一反应如下:
#define MIN(A,B) A < B ? A : B
然而这种写法在很多嵌套的使用环境中都不能返回正确的结果。比如:2 * MIN(3, 4)展开为 2 * 3 < 4 ? 3 : 4 = 6 < 4 ? 3 : 4,结果为4。
更"工程师"的写法是:
#define MIN(A,B) ((A) < (B) ? (A) : (B))
还有好奇心的同学可以参考:宏定义的正确写法,三目运算的宏定义
从这个示例中,我就在想如何能保证 a and b or c 中 b 为真或者 b 不产生歧义呢?
诚然,要想知道Lua中三目运算的形式,只需通过搜索就可以找到想要的答案。上述的推理过程多少有点先知道答案,故意往答案上靠的嫌疑。不过我坚信证明一个问题,结论并不是最重要的,重要的是论证的过程。本文仅以我对Lua粗浅的认知来尝试还原一般化的Lua三目运算的推导过程,如有更好的推理过程,可以一起交流。