「条件演算子」の版間の差分
24行目: | 24行目: | ||
例えば、[[Java]]言語では、次のように用いる。 |
例えば、[[Java]]言語では、次のように用いる。 |
||
< |
<syntaxhighlight lang="java"> |
||
int weight; |
int weight; |
||
... |
... |
||
String message = weight <= 100 ? "OK" : "積載量オーバー"; |
String message = weight <= 100 ? "OK" : "積載量オーバー"; |
||
</syntaxhighlight> |
|||
</source> |
|||
この場合、変数<code>weight</code>の値が<code>100</code>以下であれば変数<code>message</code>に<code>"OK"</code>という文字列が代入され、それ以外であれば<code>"積載量オーバー"</code>という文字列が代入される。これは通常の[[if文|if-else文]]を用いて書いた次の例と同じ意味であり、[[コンパイル]]した結果はしばしば同じものとなる。 |
この場合、変数<code>weight</code>の値が<code>100</code>以下であれば変数<code>message</code>に<code>"OK"</code>という文字列が代入され、それ以外であれば<code>"積載量オーバー"</code>という文字列が代入される。これは通常の[[if文|if-else文]]を用いて書いた次の例と同じ意味であり、[[コンパイル]]した結果はしばしば同じものとなる。 |
||
< |
<syntaxhighlight lang="java"> |
||
String message; |
String message; |
||
if (weight <= 100) { |
if (weight <= 100) { |
||
37行目: | 37行目: | ||
message = "積載量オーバー"; |
message = "積載量オーバー"; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
条件演算子はこの例のように、条件によって異なる値をある処理(上の例では<code>message</code>への代入)に適用する、という場合に記述を簡潔にすることができる。 |
条件演算子はこの例のように、条件によって異なる値をある処理(上の例では<code>message</code>への代入)に適用する、という場合に記述を簡潔にすることができる。 |
||
[[C言語]]および[[C++]]では、変数宣言時の初期化に条件演算子を用いることで、再代入を許可しない<code>const</code>修飾された変数を定義することができるようになる。さらにC++においては、if-else文による初期化では必要な、変数宣言時のデフォルト[[コンストラクタ]]が不要となる。 |
[[C言語]]および[[C++]]では、変数宣言時の初期化に条件演算子を用いることで、再代入を許可しない<code>const</code>修飾された変数を定義することができるようになる。さらにC++においては、if-else文による初期化では必要な、変数宣言時のデフォルト[[コンストラクタ]]が不要となる。 |
||
< |
<syntaxhighlight lang="c++"> |
||
const std::string message(weight <= 100 ? "OK" : "積載量オーバー"); |
const std::string message(weight <= 100 ? "OK" : "積載量オーバー"); |
||
</syntaxhighlight> |
|||
</source> |
|||
==== 演算子の結合性 ==== |
==== 演算子の結合性 ==== |
||
70行目: | 70行目: | ||
Python ではこの機能の式を条件式と呼び、構文は、C言語などとは順序が異なっている(新しい演算子ないしキーワードは導入されなかった)。[[Perl]]の後置if修飾子のような見た目になった。 |
Python ではこの機能の式を条件式と呼び、構文は、C言語などとは順序が異なっている(新しい演算子ないしキーワードは導入されなかった)。[[Perl]]の後置if修飾子のような見た目になった。 |
||
< |
<syntaxhighlight lang="python"> |
||
<真の場合の値> if <条件式> else <偽の場合の値> |
<真の場合の値> if <条件式> else <偽の場合の値> |
||
</syntaxhighlight> |
|||
</source> |
|||
=== Visual Basic === |
=== Visual Basic === |
||
90行目: | 90行目: | ||
条件演算子をサポートしない言語であっても、ifが文ではなく式となっている言語では、if式を用いることで同等の機能を実現できる。例えば[[F Sharp|F#]]には組み込みの条件演算子はないが、以下のようにif式で代用できる。 |
条件演算子をサポートしない言語であっても、ifが文ではなく式となっている言語では、if式を用いることで同等の機能を実現できる。例えば[[F Sharp|F#]]には組み込みの条件演算子はないが、以下のようにif式で代用できる。 |
||
< |
<syntaxhighlight lang="fsharp"> |
||
printfn "Now %s." (if (System.DateTime.Now.Hour >= 12) then "PM" else "AM") |
printfn "Now %s." (if (System.DateTime.Now.Hour >= 12) then "PM" else "AM") |
||
</ |
</syntaxhighlight>その他、無名関数を応用したものもある。例えばSmalltalkでは関数呼び出しに相当するメッセージ式に無名関数に相当するブロックを渡すことで条件式を実現している。<syntaxhighlight lang="smalltalk"> |
||
value := 0 < 1 ifTrue:[ 1 ] ifFalse: [ 2 ]. |
value := 0 < 1 ifTrue:[ 1 ] ifFalse: [ 2 ]. |
||
</syntaxhighlight>なお、この#ifTrue:#ifFalse:は分岐専用の構文ではなくメッセージ式の一例に過ぎない。メッセージ式は誰でも追加できるため、標準のライブラリーだけでも下記のような亜種が存在する。<syntaxhighlight lang="smalltalk"> |
</syntaxhighlight>なお、この#ifTrue:#ifFalse:は分岐専用の構文ではなくメッセージ式の一例に過ぎない。メッセージ式は誰でも追加できるため、標準のライブラリーだけでも下記のような亜種が存在する。<syntaxhighlight lang="smalltalk"> |
2020年7月5日 (日) 22:48時点における版
条件演算子(英: conditional operator)は、プログラミング言語の演算子で、条件文と同様な意味があるが、文ではなく値を持つ式になる。評価されると、条件式の値により異なる式が評価され、異なる値になる。
なお、C言語やC++など一部のプログラミング言語において、条件演算子とは後述する「? :」(ハテナマークとコロン) の演算子の名称である。
概要
「If 〜 Then 〜 Else 〜」にあたる三項演算子があり、ほぼ唯一の、プログラミング言語において一般的な三項演算子である。また「If 〜 Then 〜 if」にあたる二項演算子もある。
三項演算子は、条件式・真式・偽式の3つのオペランドを結ぶ。二項演算子の場合は、条件式と、真式または偽式のいずれかの、2つのオペランドを結ぶ。
条件文との違いは、
- 真式・偽式は式(条件文における節のように文を置くことができない)
- 式であるため値を持つ
である。
種類
三項演算子
C言語などには、次の構文の三項の条件演算子がある。
<条件式> ? <真式> : <偽式>
3項を結ぶ必要上、「?」と「:」の2つの記号を使うが、演算子としては1つの演算子である。
<条件式>
は真 (true) または偽 (false) の論理値を返す論理式 (ブール型) である(あるいは論理値に暗黙に型変換可能な型を返す)。真式と偽式は同じ型の値を返さなければならない(暗黙に型変換可能なら許されることもある)。
この構文自身も式であるので値をもち、その値は上記<真式>
または<偽式>
の値のいずれかである。<条件式>
が真の場合は<真式>
、偽の場合は<偽式>
の値となる。
例えば、Java言語では、次のように用いる。
int weight;
...
String message = weight <= 100 ? "OK" : "積載量オーバー";
この場合、変数weight
の値が100
以下であれば変数message
に"OK"
という文字列が代入され、それ以外であれば"積載量オーバー"
という文字列が代入される。これは通常のif-else文を用いて書いた次の例と同じ意味であり、コンパイルした結果はしばしば同じものとなる。
String message;
if (weight <= 100) {
message = "OK";
} else {
message = "積載量オーバー";
}
条件演算子はこの例のように、条件によって異なる値をある処理(上の例ではmessage
への代入)に適用する、という場合に記述を簡潔にすることができる。
C言語およびC++では、変数宣言時の初期化に条件演算子を用いることで、再代入を許可しないconst
修飾された変数を定義することができるようになる。さらにC++においては、if-else文による初期化では必要な、変数宣言時のデフォルトコンストラクタが不要となる。
const std::string message(weight <= 100 ? "OK" : "積載量オーバー");
演算子の結合性
条件演算子の結合性(associativity)は、CやJavaやPerlなどでは、a ? b : c ? d : e
は a ? b : (c ? d : e)
という意味だが、PHPの三項演算子[1]では (a ? b : c) ? d : e
なので注意が必要である。
論理演算子
二項の論理演算子(Cの標準規格の用語では「論理AND演算子」「論理OR演算子」)も、条件演算子のような意味を持っており(短絡評価)、Javaでは条件AND演算子と条件OR演算子という名前である。
<条件式> && <真式> <条件式> || <偽式>
1行目は、<条件式>
が真の場合にのみ<真式>
が評価される。偽の場合は条件式が評価されるのみである。式の値は、<条件式>
が真の場合は<真式>
、偽の場合は<条件式>
がそのまま返される。
2行目の構文も、真偽が逆であることを除けば同様である。
なお、Javaの演算子 &
および |
はオペランドの型がboolean
型の場合はビット演算子ではなく論理演算子となるが、両方のオペランドを必ず評価し、短絡評価はされない。C#も同様である。
Pascalのand
演算子とor
演算子が短絡評価かどうかは処理系依存である。
Ruby
Rubyでは、C と同じ形で三項演算子を使うことができる。しかし、Ruby の場合は if も文ではなく式なので、( A ? B : C )
ではなく if A then B else C end
と書くほうが好まれている。
Python
Pythonにおいては、Cの条件演算子と同じ機能は、構文に関する論争のため長い間実装されなかったが(論理演算子を使ったハックでなんとか似たことができる[1]というのもあった)、PEP 308として承認され、2006年9月の2.5 releaseに追加された[2]。
Python ではこの機能の式を条件式と呼び、構文は、C言語などとは順序が異なっている(新しい演算子ないしキーワードは導入されなかった)。Perlの後置if修飾子のような見た目になった。
<真の場合の値> if <条件式> else <偽の場合の値>
Visual Basic
Visual Basic(2008より前)、VBAには演算子はないが、同じように使える関数 Iif がある。
Iif(<条件式>, <真式>, <偽式>)
ただし条件演算子と違い、真式・偽式いずれも関数の引数なので、条件式の真偽にかかわらず双方とも評価される。条件に合わない側の値は捨てられるので値に影響はないが、真式・偽式に副作用がある(何か出力する、グローバル変数を書き換えるなど)場合は挙動が異なってくる。
Visual Basic 2008以降には[3]、条件演算子と同様の短絡評価をおこなうIf演算子がある。
If(<条件式>, <真式>, <偽式>) 'または If(<式1>, <式2>)
3引数の場合は、if-then-elseと同様の意味である。2引数の場合は、式1がNothingでない場合は式1の値を、式1がNothingの場合は式2の値を返す[4]。
条件演算子とif式
条件演算子をサポートしない言語であっても、ifが文ではなく式となっている言語では、if式を用いることで同等の機能を実現できる。例えばF#には組み込みの条件演算子はないが、以下のようにif式で代用できる。
printfn "Now %s." (if (System.DateTime.Now.Hour >= 12) 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 ].
関連する演算子
- 条件演算子:
A ? B : C
- Null合体演算子:
A ?? B
など (null時のデフォルト値設定) - エルビス演算子:
A ?: B
(false時のデフォルト値設定) - Null条件演算子:
A?.B
など (nullチェックの自動化)
脚注・参照
- ^
(c and (x,) or (y,))[0]
のようにする。要素数がゼロ個より多いタプルはPythonではtruthyであることを利用している(ので、xの値がfalsyな値であっても誤動作しない)。 - ^ PEP 308
- ^ Visual Basic 言語の新機能
- ^ If 演算子 (Visual Basic)