2018年8月15日 星期三

Lua三元運算子

問題

最近在寫Lua的時候遇到一個有趣的問題
關於短路求值,我們看一下下面的程式碼
 local result = a and b or c;
上面是 Lua 的三元運算,看起來相當合理
如果 a 的判斷是 true 那麼 result 就是 b 不然就是 c
但是在 Lua 中,如果 b 剛好是 nil 或是 false 的話,result 的結果會是 c
這個不是我們要的答案
必須想個辦法解決

為什麼

這個問題的原因是因為 and 和 or 是短路求值
短路求值可以有效的處理下面的程式碼
 -- 只有 dog 這個物件存在才會去判斷 dog 是否在睡覺
 if dog and dog:isSleep() then
  ...
  ...
 end
只在有需要的時候才會去執行第二個條件
Lua 做邏輯判斷的時候只有 nil 和 false 是假的,其他都是真的
and 判斷會回傳"假"的那個條件
or 判斷則是回傳"真" 的那個條件
所以
 a and b or c
這個判斷下,如果 a 判斷的結果是真,結果應該會是 b or c
可是 b 的內容卻是 nil 或是 false,所以結果就會是 c 了
如果 a 判斷的結果為假,那麼 and 就不會處理
直接進行 or 判斷,這個時候的結果會是 c
也就是說,只要 b 的內容是 nil 或是 false 的話
這個判斷的結果一定會是 c

解決

有很多方式可以避開這個問題
比如改成
 local result = not a and c or b;
或是
 local result = c;
 if a then
  result = b;
 end
但是這些都是治標不治本(這邊是假設你一定要用三元運算子來處理邏輯)
最好的方式是用 table 將數值包裝起來,等判斷完再取值
 -- best solution
 local result = (a and {b} or {c})[1];
搞定!
回家收工!

參考

短路求值
Lua邏輯判斷

沒有留言:

張貼留言

Lua 5.1 __gc

__gc lua 5.2 開始有 __gc 這個元函數可以知道什麼時候被釋放掉 當 table 被回收時會呼叫這個函數 我們可以在這個函數中處理資源釋放等操作 不過 lua 5.1 中對於 table 并不支援,我們先看一下在 lua 5.2 中 這個 __gc 怎...