条件演算子

条件演算子は、プログラミング言語の演算子で、条件文と同様な意味があるが、文ではなく値を持つ式になる。評価されると、条件式の値により異なる式が評価され、異なる値になる。

なお、C言語やC++など一部のプログラミング言語において、条件演算子とは後述する「? :」 の演算子の名称である。

1. 概要
-----

「If Then Else 」にあたる三項演算子があり、ほぼ唯一の、プログラミング言語において一般的な三項演算子である。また「If Then if」にあたる二項演算子もある。

三項演算子は、条件式・真式・偽式の3つのオペランドを結ぶ。二項演算子の場合は、条件式と、真式または偽式のいずれかの、2つのオペランドを結ぶ。

条件文との違いは、

真式・偽式は式
式であるため値を持つである。

2. 種類
-----

2.1. C言語など
----------

C言語などには、次の構文の三項の条件演算子がある。 ? : 3項を結ぶ必要上、「?」と「:」の2つの記号を使うが、演算子としては1つの演算子である。

は真  または偽  の論理値を返す論理式  である。真式と偽式は同じ型の値を返さなければならない。

この構文自身も式であるので値をもち、その値は上記またはの値のいずれかである。が真の場合は、偽の場合はの値となる。

例えば、Java言語では、次のように用いる。 int weight; ... String message = weight <= 100 ? "OK" : "積載量オーバー"; この場合、変数weightの値が100以下であれば変数messageに"OK"という文字列が代入され、それ以外であれば"積載量オーバー"という文字列が代入される。これは通常のif-else文を用いて書いた次の例と同じ意味であり、コンパイルした結果はしばしば同じものとなる。 String message; if  { message = "OK"; } else { message = "積載量オーバー"; } 条件演算子はこの例のように、条件によって異なる値をある処理に適用する、という場合に記述を簡潔にすることができる。

C言語およびC++では、変数宣言時の初期化に条件演算子を用いることで、再代入を許可しないconst修飾された変数を定義することができるようになる。さらにC++においては、if-else文による初期化では必要な、変数宣言時のデフォルトコンストラクタが不要となる。 const std::string message;

2.1.1. 演算子の結合性
--------------

条件演算子の結合性は、CやJavaやPerlなどでは、a ? b : c ? d : e は a ? b :  という意味だが、PHPの三項演算子[1]では  ? d : e なので注意が必要である。

2.2. Ruby
---------

Rubyでは、 ? : というC と同じ形で条件演算子を使うことができる。しかし、Ruby の場合は if も文ではなく式なので、入れ子や複数行になる場合は、条件演算子ではなくifを使用する方が好まれている。

2.3. Python
-----------

Pythonにおいては、Cの条件演算子と同じ機能は、構文に関する論争のため長い間実装されなかったが、PEP 308として承認され、2006年9月の2.5 releaseに追加された。

Python ではこの機能の式を条件式と呼び、構文は、C言語などとは順序が異なっている。Perlの後置if修飾子のような見た目になった。

if else

2.4. Visual Basic
-----------------

Visual Basic、VBAには演算子はないが、同じように使える関数 Iif がある。 Iif ただし条件演算子と違い、真式・偽式いずれも関数の引数なので、条件式の真偽にかかわらず双方とも評価される。条件に合わない側の値は捨てられるので値に影響はないが、真式・偽式に副作用がある場合は挙動が異なってくる。

Visual Basic 2008以降には、条件演算子と同様の短絡評価をおこなうIf演算子がある。

If 'または If

3引数の場合は、if-then-elseと同様の意味である。2引数の場合は、式1がNothingでない場合は式1の値を、式1がNothingの場合は式2の値を返す。

3. 論理演算子の短絡評価
-------------

論理演算子の短絡評価を利用して条件演算子のような処理を書くことができる。

短絡評価を持つ論理演算子について、論理積 //expr1// AND //expr2//}} は左辺の式 //expr1//}} が偽値なら右辺の式 //expr2//}} は評価されない。 同様に、論理和 //expr1// OR //expr2//}} は左辺の式 //expr1//}} が真値なら右辺の式 //expr2//}} は評価されない。

従って、左辺 //expr1//}} を条件式とし、その結果が真値の場合に評価されるべき式を論理積の右辺の式 //expr2//}} に書け、また同様に左辺の式 //expr1//}} が偽値の場合に評価されるべき式を論理和の右辺の式 //expr2//}} に書ける。

条件演算子ないしif-else式を短絡評価する論理演算子で模倣すると、

と書ける。上記の式は、//cond//}} が偽値なら //expr1//}} を評価せずに//expr2//}} を評価し、//cond//}} が真値なら //expr2//}} を評価しない。 条件演算子などとの相違点として、論理演算子の評価結果がブーリアンに変換されるプログラミング言語では //expr1//}} および //expr2//}} の値そのものは利用できない。

4. 条件演算子とif式
------------

条件演算子をサポートしない言語であっても、ifが文ではなく式となっている言語では、if式を用いることで同等の機能を実現できる。例えばF#には組み込みの条件演算子はないが、以下のようにif式で代用できる。

printfn "Now %s."  then "PM" else "AM")その他、無名関数を応用したものもある。例えばSmalltalkでは関数呼び出しに相当するメッセージ式に無名関数に相当するブロックを渡すことで条件式を実現している。 value := 0 < 1 ifTrue:[ 1 ] ifFalse: [ 2 ].なお、この#ifTrue:#ifFalse:は分岐専用の構文ではなくメッセージ式の一例に過ぎない。メッセージ式は誰でも追加できるため、標準のライブラリーだけでも下記のような亜種が存在する。 value := 0 < 1 ifTrue:[ 1 ]. value := value ifNil:[ 1 ] ifNotNil[ 2 ]. value := value ifNil:[ 1 ]. value := value ifNotNil:[ :argument | 1 ]. value := value at: 1 ifAbsent:[ 0 ].

<WtXmlEndTag />

5. 関連する演算子
----------

条件演算子: A ? B : C
Null合体演算子: A ?? B など 
エルビス演算子: A ?: B 
Null条件演算子: A?.B など 

6. 脚注
-----

6.1. 注釈
-------

6.2. 出典
-------

de:Fragezeichen#Bedingungsoperator