三項演算

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)」を使用します。つまり、必要なときだけ第2オペランドを評価します。(『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言語には定番の試験問題があるのを思い出しました。マクロ定義を使って2つの値のうち小さい方を返す方法を書いてください、というものです。

学生時代に初めてこの問題を見たとき、最初に思いついたのは次のようなものでした:

#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 があいまいにならないようにするにはどうすればいいのかを考えました。

  • and の演算子優先順位は or より高いため、単純に演算順序を変えても意味がありません。
  • そこで Lua の万能な table を思い出しました。a,b,c をすべて table に入れて b の存在を変えられないでしょうか? {nil} も true とみなされるオブジェクトであることに注意してください。
    a,b,c をすべて table に置き換えます:{a} and {b} or {c}。
  • 三項演算では a が条件で、結果は b または c です。実際、a を table に入れる必要はありません。そうしないと {a} は常に true となり、条件としての意味を失います。一方、{b} or
    {c} の結果も必ず table になり、その table は要素を1つだけ持ちます。したがって
  • 以上のことから、より一般化した Lua の三項演算は次のようになります:(a and {b} or {c})

まとめ

確かに、Lua における三項演算の形式を知りたいなら、検索すれば答えはすぐに見つかります。上記の推論の過程は、多少なりとも答えを先に知っていて、わざと答えに寄せている感があります。しかし私は、ある問題を証明する際に、結論が最も重要なのではなく、議論のプロセスが重要だと信じています。この記事では、Lua に対する私の浅い知識に基づいて、一般化した Lua の三項演算の導出過程を再現しようと試みたものです。もしもっと良い推論の過程があれば、ぜひ交流しましょう。

出典:https://blog.csdn.net/u010832643/article/details/77546887