三項演算子 ?:
?:
演算子は、if-else
文とよく似た働きをする。
if
文は、true
の場合にはそのブロックを実行し、false
の場合にはそのブロックを実行する。ご存じのとおり、これは文であるため値はない。if
は、コードブロックの実行に影響を与えるだけだ。
一方、?:
演算子は式だ。if-else
文と同様に機能するほか、値を生成する。上記のコードと同等のものは、次の通りだ。
?:
演算子は3つの式を使用するため、三項演算子と呼ばれる。
この演算子によって生成される値は、真式または偽式のいずれかの値になる。これは式であるため、式を使用できる場所ならどこでも使用できる。
次の例は、?:
演算子とif-else
文を比較している。これらの例のような場合、三項演算子はより簡潔だ。
- 初期化
変数を、閏年の場合は366、そうでない場合は365で初期化するには:
if
文を使用する場合、この処理を行う1つの方法は、明示的な初期値なしで変数を定義し、次に意図した値を割り当てる方法だ。if
を使用する別の方法としては、閏年ではない年の値で変数を初期化し、閏年であればその値を加算する方法がある。 - 出力
条件に応じてメッセージの一部を異なる方法で出力する:
if
を使用すると、メッセージの最初と最後の部分を別々に表示することができる:または、メッセージ全体を別々に表示することもできる:
- 計算
バックギャモンゲームで勝者の得点を、ゲームがガモンで終了した場合に2点または1点増加させる:
if
を使用した単純な等価式:if
を使用した別の方法は、まず1を加算し、その後gammonの場合に再び加算することだ:
上記の例からわかるように、特定の状況では、三項演算子を使用するとコードがより簡潔で明確になる。
三項式の型
?:
演算子の値は、真式または偽式のいずれかの値になる。これら2つの式の型は同じである必要はないが、共通の型を持つ必要がある。
2つの式の共通型は、型変換や 継承を含む比較的複雑なアルゴリズムによって決定される。さらに、式に応じて、結果の種は l値またはr値のいずれかになる。これらの概念については、後の章で説明する。
ここでは、明示的な型変換を必要とせずに両方の値を表現できる型を共通型とみなしよう。例えば、整数型int
とlong
は、どちらもlong
として表現できるため、共通型を持っている。一方、int
とstring
は、int
もstring
も自動的に他の型に変換できないため、共通型を持っていない。
式の型を簡単に決定する方法は、typeof
を使用して、その.stringof
プロパティを出力することだ。
double
はint
を表現できるが、その逆は不可能であるため、上記の三項式式の共通型はdouble
になる。
double
共通型を持たない2つの式の例を見るために、出荷するアイテムの数を報告するメッセージを作成しよう。値が12の場合は"A dozen"と出力する。それ以外の場合は、正確な数をメッセージに含める。"3items will be shipped."
メッセージの変動部分を?:
演算子で選択できると思うかもしれない:
残念ながら、式には共通の型がない。 "A dozen"
はstring
で、count
の型はint
だから、式は共通の型を持っていない。
解決策は、まずcount
をstring
に変換することだ。std.conv
モジュールにあるto!string
関数は、指定されたパラメータからstring
値を生成する。
これで、?:
演算子の2つの選択式はどちらもstring
型になったため、コードはコンパイルされ、期待どおりのメッセージが表示される。
演習
プログラムに、正の値は利益、負の値は損失を表す、純額として単一の int
値を読み込ませよう。
プログラムは、金額が正か負かによって、"gained"または"lost"を含むメッセージを表示する必要がある。例えば、"$100 lost"または"$70 gained"などである。より適切であるかもしれないが、この演習ではif
文は使用してはいけない。