Lua 中的三目運算符介紹

Lua 原生的語義並沒有實現三目運算,一般是通過邏輯運算符 and 和 or 來模擬三目運算符的。

Lua 中的三目運算符介紹Lua 中的三目運算符介紹

三目運算

熟悉 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 中的三目運算

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

完美!

Lua 中的三目運算符陷阱

按照從特殊到一般的原則:

  • 三目運算的一般形式a ? b : c

    a = true,結果爲b
    a = false,結果爲c

  • 對應Lua中的a and b or c

    • b = true
      • a = true
        • a and b –> true
        • b or c –> b
      • a = false
        • a and b –> false
        • b or c –> c
    • b = false
      • a = true
        • a and b –> false
        • b or c –> c
      • a = false
        • a and b –> false
        • b or c –> c

可以看到當 b = false 時,Lua模擬的 a and b or c 始終返回 c 並不能還原三目運算符的原貌。

《Lua程序設計》也建議這種情況使用 if-else 來避免。

一般化的 a and b or c

那麼有沒有辦法可以解決 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 不產生歧義呢?

  1. and的運算優先級高於or,簡單的改變運算順序並沒有用。
  2. 這時就想到了lua中萬能的table,能不能把a,b,c都放到table中來改變b的存在呢?要注意{nil}也是一個爲true的對象。
    a,b,c都替換爲table:{a} and {b} or {c}。
  3. 三目運算中a是條件,結果是b或者c。其實a並不需要放入table中,否則{a}就始終爲true了,失去了條件的意義。而{b} or
    {c}的結果也必然是一個table,該table只有一個元素。那麼通過[1]即可訪問。
  4. 綜上所述,更一般化的Lua三目運算爲:(a and {b} or {c})[1]
總結

誠然,要想知道Lua中三目運算的形式,只需通過搜索就可以找到想要的答案。上述的推理過程多少有點先知道答案,故意往答案上靠的嫌疑。不過我堅信證明一個問題,結論並不是最重要的,重要的是論證的過程。本文僅以我對Lua粗淺的認知來嘗試還原一般化的Lua三目運算的推導過程,如有更好的推理過程,可以一起交流。

本文地址:https://www.linuxprobe.com/introduction-to-ternary.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章