

コンピュータプログラミングにおいて、条件文は条件(ブール式)の値に基づいてプログラムの制御フローを制御します。条件式は、制御フローを変更する副作用なしに値を評価し、結果を出力します。
多くのプログラミング言語( C言語など)には、明確な条件文と式があります。純粋関数型プログラミングでは条件式に副作用はありませんが、条件式を持つ多くの関数型プログラミング言語(Lispなど)では副作用がサポートされています。
if-then-else 文の構文は言語によって異なりますが、一般的な構文は以下の擬似コードで示されています。条件プレースホルダーで表される部分は、真または偽のいずれかに評価される式です。真の場合、制御はconsequentに渡され、完了すると after に渡されます。偽の場合、制御はalternativeend ifに渡され、完了すると after に渡されます。else 節はオプションであるため、この部分は省略可能です。通常、consequentとalternative はどちらも単一の文または文のブロックとして記述できます。 end ifelse alternative
条件が満たされ、結果が満たされ、そうでなければ、代替案が満たされ、終了する次の例も擬似コードで、プレースホルダーをサンプル ロジックに置き換えます。
在庫が0の場合、メッセージは「新しい在庫を注文する」、そうでない場合はメッセージは「在庫があります」で終了初期のプログラミング言語、特にBASICの方言では、if-then-else 文にはgoto文しか含めることができませんでしたが、これでは読みにくいスパゲッティ コードになる傾向がありました。その結果、コード ブロックを介して制御フローをサポートする構造化プログラミングが普及し、ほとんどの BASIC バリアントおよびすべての言語で標準になりました。このようなメカニズムと原則は、PascalやModula-2などのALGOLファミリーの言語に基づいています。goto を構造化された方法で使用することは可能ですが、構造化プログラミングを使用するとそれが簡単になります。構造化された if-then-else 文は構造化プログラミングの重要な要素の 1 つであり、C、Java、JavaScript、Visual Basicなどのほとんどの一般的な言語に存在します。
慣例的にelse、節は、節と同様にthen、最も近い先行if節に対応する。しかし、ALGOL 60などの初期の言語では、ネストされた条件文の意味論は必ずしも明確ではなく、構文が常に同じ述語節を指定するには不十分であった。そのため、パーサーは、意図されたネスト階層内のおそらく多様である節のいずれかと、ランダムに the を組み合わせる可能性がある。 ifelseif
もしAなら、もしBならS 、そうでなければS2もしAなら、もしBならS 、そうでなければS2もしAならば(もしBならばS )、そうでなければS2、終了もしAならば(もしBならばS )、そうでなければS2、終了もしAならば(もしBならばS 、そうでなければS2 )もしAならば(もしBならばS、そうでなければS2 )終了これはぶら下がりelse問題として知られています。この問題は言語によって様々な方法で解決されます(言語によっては、明示的なブロック終了構文( などend if)や中括弧({⋯ })などのブロック囲みを使用する場合もあります)。
条件文の連鎖は、言語においてelse-if構文によって提供されることがよくあります。最初の条件が真となる文の後に続く文のみが実行されます。その他の文はスキップされます。プレースホルダ擬似コードでは、次のようになります。
条件1の場合、ブロック1、そうでない場合、条件2の場合、ブロック2、そうでない場合、条件3の場合、ブロック3、.. 、そうでない場合、ブロック4、終了の場合以下の擬似コードでは、ある店が商品に最大30%の割引を提供しています。割引が10%の場合、最初のif文は真となり、「30ドル支払わなければなりません" が出力されます。最初の if ステートメントの下にある他のすべてのステートメントはスキップされます。
割引< 11 %の場合は「30ドルお支払いいただく必要があります」と出力し、割引< 21 %の場合は「20ドルお支払いいただく必要があります」と出力し、割引< 31 %の場合は「10ドルお支払いいただく必要があります」と出力します。の代わりにを使用する場合は、 のみend ifが必要です。 else ifelseif
ALGOL 68では、1968年の「報告書草案」( ALGOL速報第26号の補足として配布)では、依然として「短縮された」条件文で太字のキーワードelsfが使用されていました。[ 1 ]その後、 elif の綴りは「アルゴリズム言語ALGOL 68の改訂報告書」(1973年)で標準化され、太字の単語とその「簡潔な」記号の両方が記載されています。elifは短縮形の に対応します。[ 2 ]if ~ then ~ elif ~ else ~ fi|:( ~ | ~ |: ~ | ~ | ~ )
Adaでは、elseifキーワードは2 つの単語 の糖衣構文です。PHP も、中括弧構文とコロン構文の両方で キーワードをサポートしています[ 3 ] 。PerlとRuby は、複数のandステートメントに必要な多数の中括弧を回避するためにキーワード を提供しています。Python では、構造は中括弧ではなくインデントによって示されるため、andを繰り返し使用すると条件ごとにインデントを増やす必要がある ため、特別なキーワードを使用します。Visual Basic はをサポートしています。[ 4 ] 同様に、初期のUNIX シェル(後に POSIX シェル構文[ 5 ]にまとめられました)もelifを使用していますが、スペース、改行、またはその両方で区切るオプションを提供しています。 elseifelseifelsififelseelifelseifElseIf
しかし、 Simula、Pascal、BCPL、Cなど、Algolからより直接的に派生した多くの言語では、この特別な構文は存在しません。また、 Java、ECMAScriptelse ifなど、Cから派生した多くの構文にも存在しません。これらの言語では、任意の単一の文(この場合は)をブロックで囲むことなく条件文に続けることができる ため、この構文は機能します。if cond...
条件文のシーケンス内のすべての項が 単一の式の値をテストする場合(例:if x = 0、、 else if x = 1else if x = 2 …)、代替手段としてswitch文を使用できます。switch文を持たない言語では、これらは連鎖的なif-then-elseとして記述できます。
switch文は多方向分岐をサポートしており、多くの場合、式の値を定数値と比較し、最初に一致したコードに制御を移します。一致するものが見つからない場合は、通常、デフォルトのアクションを実行するための規定があります。最適化コンパイラは、制御テーブルを使用してswitch文のロジックを実装する場合があります。動的言語では、ケースは定数式に限定されず、パターンマッチングにまで拡張される可能性があります。右側のシェルスクリプトの例では、「*)」によってデフォルトのケースが任意の文字列に一致する正規表現として実装されています。
エドガー・ダイクストラのガード付きコマンド言語(GCL)は、ブール値のガード(条件に対応)とそれに対応する文からなるコマンドのリストとして条件付き実行をサポートします。GCLでは、ガードが真である文のうち1つだけが評価されますが、どの文が評価されるかは任意です。このコードでは、
G0 → S0の場合 □ G1 → S1 ... □ Gn → Sn フィ
G iはガード、S iは文です。ガードがどれも真でない場合、プログラムの動作は未定義です。
GCL は主にプログラムの推論を目的としていますが、同様の表記法がConcurrent Pascalやoccamでも実装されています。
Fortran 77までのFortranにおける最も初期の条件文は、値(整数型、実数型、倍精度型)が<0、0、>0のいずれであるかに応じて3つのラベルのいずれかにジャンプする算術if文であった。[ 6 ]
次のコードでは、 の値に基づいて制御がラベルの 1 つに渡されますe。
IF ( e )ラベル1 、ラベル2 、ラベル3これは次のシーケンスと同等です。
e_temp = e IF ( e_temp . LT . 0 ) GOTOラベル1 IF ( e_temp . EQ . 0 ) GOTOラベル2 IF ( e_temp . GT . 0 ) GOTOラベル3gotoのように動作する算術 if は非構造化プログラミングであり、構造化プログラミングではありません。IBM 704コンピュータにおける Fortran のオリジナル実装では、if は唯一の条件文でした。このコンピュータでは、テスト分岐命令コードには、これらの 3 つの状態に対応する 3 つのアドレスがありました。他のコンピュータでは、正、ゼロ、負、偶数、オーバーフロー、キャリーなどの「フラグ」レジスタが最後の算術演算に関連付けられており、「アキュムレータが負の場合に分岐」、次に「アキュムレータがゼロの場合に分岐」といった命令が使用されるでしょう。式は一度だけ評価され、整数演算などオーバーフローが発生する可能性のある場合には、オーバーフローフラグまたはキャリーフラグも考慮されることに注意してください。
算術IF文は、Fortran 90規格以降、廃止予定とされていました。Fortran 2018規格では削除されました。しかし、ほとんどのコンパイラは、従来のコードとの互換性を保つため、引き続きサポートしています。
他の言語とは対照的に、Smalltalkでは条件文は言語構成要素ではなく、クラス内で2つのパラメータ(両方ともクロージャ)Booleanを取る抽象メソッドとして定義されています。には2つのサブクラス(と)があり、どちらもメソッドを定義しており、最初のクロージャのみを実行し、2番目のクロージャのみを実行します。[ 7 ]BooleanTrueFalseTrueFalse
var =条件ifTrue: [ 'foo' ] ifFalse: [ 'bar' ] JavaScriptはC言語の構文に似たif-else文をサポートしています。次の例では、ランダムな浮動小数点数(0から1までの値)が0.5より大きい場合に真となる条件文を使用しています。この文では、これを使用して、以下のどちらかをランダムに出力します。Math.random()<0.5表が出ました!またはテイルスを手に入れました!。
if ( Math . random () < 0.5 ) { console . log ( "表でした!" ); } else { console . log ( "裏でした!" ); }条件文は以下のように連鎖させることができます。
var x = Math.random ( ); if ( x < 1 / 3 ) { console.log ( " 1人が勝ちました!" ) ; } else if ( x < 2 / 3 ) { console.log ( " 2人が勝ちました!" ) ; } else { console.log ( "3人が同点です!" ) ; }ラムダ計算では、if-then-else 条件の概念は次の式を使用して表現できます。
真 = λx. λy. x 偽 = λx. λy. y もしそうでなければ = (λc. λx. λy. (cxy))
注意: ifThenElse に左と右の条件として 2 つの関数が渡される場合、選択した関数を実際に呼び出すには、ifThenElseの結果に空のタプルも渡す必要があります。そうしないと、 ifThenElse は呼び出されずに 関数オブジェクトを返します。()
定義なしで数値を使用できるシステム (Lisp、従来の紙の数学など) では、上記は次のような単一のクロージャとして表現できます。
(( λtrue. λfalse. λifThenElse. ( ifThenElse true 2 3 ) )( λx. λy. x )( λx. λy. y )( λc. λl. λr. c l r ))ここで、true、false、 ifThenElseはそれぞれの定義にバインドされ、ブロックの最後にそれぞれのスコープに渡されます。
これに対する実用的な JavaScript の類似例 (厳密さのために単一変数の関数のみを使用) は次のとおりです。
var computeResult = (( _true => _false => _ifThenElse => _ifThenElse ( _true )( 2 )( 3 ) )( x => y => x )( x => y => y )( c => x => y => c ( x )( y )));上記の多変数関数を使用したコードは次のようになります。
var computeResult = (( _true , _false , _ifThenElse ) => _ifThenElse ( _true , 2 , 3 ) )(( x , y ) => x , ( x , y ) => y , ( c , x , y ) => c ( x , y ));数字を想定するシステムを使用しない前述の例の別のバージョンを以下に示します。
最初の例では最初の分岐が実行されることを示しており、2 番目の例では 2 番目の分岐が実行されることを示しています。
(( λtrue. λfalse. λifThenElse. ( ifThenElse true ( λFirstBranch. FirstBranch ) ( λSecondBranch. SecondBranch )) )( λx. λy. x )( λx. λy. y )( λc. λl. λr. c l r ))(( λtrue. λfalse. λifThenElse. ( ifThenElse false ( λFirstBranch. FirstBranch ) ( λSecondBranch. SecondBranch )) )( λx. λy. x )( λx. λy. y )( λc. λl. λr. c l r ))Smalltalk は、真偽の表現に同様の考え方を使用しており、 と はTrue、メッセージifTrue/ifFalseに異なる False応答をするシングルトン オブジェクトです。
Haskell はブール型にまさにこのモデルを使用していましたが、執筆時点では、ほとんどの Haskell プログラムは、別の関数にラップされるか、このページの Haskell セクションに示すように再実装されない限り 、 ifThenElseとは異なり構成されない構文糖構造を使用しています。ifathenbelsec
多くの言語は条件式をサポートしています。条件式は文とは異なり、制御フローを制御するのではなく、値として評価されます。条件式の概念は、 1950年代後半にジョン・マッカーシーが記号処理とLISPの研究中に初めて開発されました。
ALGOL 60およびALGOLファミリーの他のメンバーでは、if–then–else式として が使用できます。条件式を含めるというアイデアはジョン・マッカーシーによって提案されましたが、ALGOL委員会はマッカーシーの数学的構文ではなく英語の単語を使用することを決定しました。
myvariable := x > 20の場合1、そうでない場合2複合ステートメントはすべて、特徴的な閉じ括弧によって終了(保護)されます。
IF条件THEN文[ ELSE文] FI 「簡潔な」形式: ( 条件 | ステートメント | ステートメント )
IF条件1 THEN文ELIF条件2 THEN文 [ ELSE文 ] FI 「簡潔な」形式: ( 条件1 | ステートメント |: 条件2 | ステートメント | ステートメント )
この方式は、ぶら下がっている else の問題を回避するだけでなく、埋め込みステートメントBEGINシーケンスでand を使用する必要も回避します。 END
CASEスイッチIN文、文、... [ OUT文 ] ESAC 「簡潔な」形式: ( switch | ステートメント、ステートメント、... | ステートメント )
CASE switch1 INステートメント、ステートメント、... OUSE switch2 INステートメント、ステートメント、... [ OUTステートメント ] ESAC CASEステートメント の「簡潔な」形式: ( switch1 | ステートメント、ステートメント、... |: switch2 | ステートメント、ステートメント、... | ステートメント )
簡潔な記号を使用した選択節の例:
PROC月の日数 = ( INT年, 月) INT : (月| 31, (年÷×4=0 ∧ 年÷×100≠0 ∨ 年÷×400=0 | 29 | 28)、 31、30、31、30、31、31、30、31、30、31 );
条件式は常にLispの基本的な要素です 。純粋なLISPでは関数が使用されます。Scheme 、Racket、Common LispCONDなどの方言では、以下のようになります。
;; Scheme ( define ( myvariable x ) ( if ( > x 12 ) 1 2 )) ; 'x'の値に応じて、'myvariable'に1または2を割り当てます;; Common Lisp ( let (( x 10 )) ( setq myvariable ( if ( > x 12 ) 2 4 ))) ; 'myvariable'を2に代入するHaskell 98にはif式のみがあり、if文はなく、elseすべての式は何らかの値を持たなければならないため、この部分は必須です。[ 8 ]他の言語では条件文で表現されるロジックは、通常、再帰関数では パターンマッチングで表現されます。
Haskellは遅延評価なので、 ifのような制御構造を通常の式として記述することができます。遅延評価とは、if関数が条件と適切な分岐のみを評価することを意味します(正格言語では3つすべてを評価することになります)。これは次のように記述できます。[ 9 ]
if' :: Bool -> a -> a -> a if' True x _ = x if' False _ y = yCおよび関連言語は、次のような条件式を提供する 三項演算子をサポートしています。
条件 ?真値 :偽値
条件が真の場合、式は真値(true-value)と評価され、そうでない場合は偽値(false-value)と評価されます。次のコードでは、x > 10の場合、rは「foo」に代入され、そうでない場合は「bar」に代入されます。
r = x > 10 ? "foo" : "bar" ;同じことを if 文で実現しようとすると、複数の文が必要になり、r2 回記述する必要が生じます。
もしx > 10ならr = "foo" ;そうでなければr = " bar" ;明示的なif-then文の方が読みやすく、三項演算子よりも効率的なコードにコンパイルできると主張する人もいます[ 10 ]。一方、簡潔な式の方が繰り返し節が少ないため読みやすく優れていると主張する人もいます。
Visual Basicやその他の言語では、条件式として使用できる関数 という関数IIfが用意されています。ただし、これは真の条件式のように動作しません。なぜなら、常に真と偽の両方の分岐が評価されるからです。どちらか一方の結果は破棄され、もう一方の結果はIIf関数によって返されるだけです。
Tcl ではifはキーワードではなく関数です(Tclではコマンドまたは と呼ばれますproc)。例えば
if { $x > 10 } { "Foo!"と出力します}という関数を呼び出し、if2つの引数を渡します。最初の引数は条件、2番目の引数は真の分岐です。どちらの引数も文字列として渡されます(Tclでは、中括弧で囲まれたものはすべて文字列です)。
上記の例では、関数を呼び出す前に条件が評価されていません。代わりに、関数の実装はif条件を文字列値として受け取り、呼び出し元のスコープ内でこの文字列を式として評価する責任を負います。[ 11 ]
このような動作は、コマンドuplevelとexprコマンドを使用することで可能になります。Uplevelを使用すると、新しい制御構造をTclプロシージャとして実装できます(例えば、uplevelを使用してwhile構造をTclプロシージャとして実装できます)。[ 12 ]
は実際には関数であるためif、値も返します。コマンドからの戻り値は、実行された本体スクリプトの結果、または、式がいずれも0以外で、かつbodyNが存在しない場合は空文字列となります。 [ 13 ]
Rustでは、ifは常に式です。これは、実行される分岐の値に評価されますが、()分岐が実行されない場合はユニット型に評価されます。分岐が戻り値を提供しない場合は、()デフォルトで に評価されます。if式の型がコンパイル時に判明していることを保証するために、各分岐は同じ型の値に評価される必要があります。このため、のない はデフォルトで常に に評価されるため、else他の分岐が に評価されない限り、ある分岐は事実上必須です。[ 14 ]()ifelse()
以下は、rx の値に応じて 1 または 2 を割り当てます。
x > 20の場合r = { 1 }、そうでない場合は{ 2 }とします。必要ない場合は値を省略できます。
x > 20の場合{ println! ( "xは20より大きい" ); }パターンマッチングは、条件文(if–then–elseやswitchなど)の代替手段です。Wolfram言語、MLなど、関数型プログラミング機能を備えた多くの言語で利用できます。OCaml言語で記述した簡単な例を以下に示します。
フルーツを次のものと一致させます| 「りんご」->パイを焼く| 「ココナッツ」->だんご餅を焼く| 「バナナ」->混ぜる;;パターンマッチングの強みは、アクションだけでなく値もデータのパターンに簡潔にマッチさせることができることです。以下は、これらの両方の機能を示す Haskellで書かれた例です。
マップ_ [] = []マップf ( h : t ) = f h :マップf tこのコードは関数mapを定義しています。この関数は、最初の引数(関数)を2番目の引数(リスト)の各要素に適用し、結果のリストを返します。2行は、この場合に考えられる2種類の引数、つまりリストが空の場合(空のリストを返すだけ)と、リストが空でない場合の2種類に対する関数の定義です。
パターンマッチングは厳密に言えば常に選択構造であるとは限りません。Haskellでは、常に一致することが保証された選択肢を1つだけ記述することが可能だからです。この場合、パターンマッチングは選択構造としてではなく、単に名前と値を結び付ける方法として使用されています。しかし、パターンマッチングが利用可能な言語では、選択構造として頻繁に使用されます。
Python、Perl、PHP、Objective-Cなど、連想配列やそれに類似したデータ構造を持つプログラミング言語では、条件付き代入を実装するためにそれらを使用するのが慣用的です。[ 15 ]
pet = input ( "名前を付けたいペットの種類を入力してください: " ) known_pets = { "Dog" : "Fido" , "Cat" : "Meowsles" , "Bird" : "Tweety" , } my_name = known_pets [ pet ]匿名関数を持つ言語、またはプログラマが名前付き関数を変数参照に割り当てることができる言語では、ハッシュをディスパッチ テーブルとして使用して条件付きフローを実装できます。
条件分岐命令の代替として、分岐プレディケーションがあります。プレディケーションとは、制御フローを変更する代わりに、命令を条件付きで実行できるようにするアーキテクチャ上の機能です。
この表は、各言語の最新の言語仕様を参照しています。仕様が存在しない言語については、公式にリリースされた最新の実装を参照しています。
| プログラミング言語 | 構造化されている場合 | スイッチ–セレクト–ケース | 条件式 | 算術if | パターンマッチング[A] | ||
|---|---|---|---|---|---|---|---|
| それから | それ以外 | そうでなければ | |||||
| エイダ | はい | はい | はい | はい | はい | いいえ | いいえ |
| アルゴル60 | はい | はい | 不要[C] | いいえ | はい | いいえ | いいえ |
| アルゴル68 | はい | はい | はい | はい | はい | はい -ケース節 | はい - 適合条項 |
| APL | いいえ | はい | はい | はい | はい | いいえ | いいえ |
| Bashシェル | はい | はい | はい | はい | はい | いいえ | はい |
| C、C++ | いいえ | はい | 不要[B] [C] | フォールスルー | はい | いいえ | いいえ |
| C# | いいえ | はい | 不要[B] [C] | はい | はい | いいえ | いいえ |
| コボル | 不要 | はい | 不要[C] | はい | いいえ | いいえ | いいえ |
| エッフェル | はい | はい | はい | はい | はい | いいえ | いいえ |
| F# | はい | はい | はい | はい[D] | はい | いいえ | はい |
| フォートラン | はい | はい | はい | はい | はい[G] | はい[私] | はい - タイプを選択 |
| 行く | いいえ | はい | 不要[C] | はい | いいえ | いいえ | いいえ |
| ハスケル | はい | 必要 | 不要[C] | はい[D] | はい | いいえ | はい |
| ジャワ | いいえ | はい | 不要[C] | フォールスルー[ 16 ] | はい | いいえ | いいえ |
| ECMAScript(JavaScript) | いいえ | はい | 不要[C] | フォールスルー[ 17 ] | はい | いいえ | いいえ |
| マセマティカ | いいえ | はい | はい | はい | はい | いいえ | はい |
| オベロン | はい | はい | はい | はい | いいえ | いいえ | いいえ |
| パール | いいえ | はい | はい | はい | はい | いいえ | いいえ |
| PHP | いいえ | はい | はい | フォールスルー | はい | いいえ | はい |
| Pascal、Object Pascal(Delphi) | はい | はい | 不要 | はい | いいえ | いいえ | いいえ |
| パイソン | いいえ | はい | はい | はい | はい | いいえ | はい |
| クイックベーシック | はい | はい | はい | はい | いいえ | いいえ | いいえ |
| ルビー | はい | はい | はい | はい | はい | いいえ | はい[H] |
| さび | いいえ | はい | はい | はい[D] | はい | いいえ | はい |
| スカラ | いいえ | はい | 不要[C] | フォールスルー | はい | いいえ | はい |
| SQL | はい[F] | はい | はい | はい[F] | はい | いいえ | いいえ |
| 迅速 | いいえ | はい | はい | はい | はい | いいえ | はい |
| Tcl | いいえ | はい | はい | はい | はい | いいえ | はい |
| Visual Basic、クラシック | はい | はい | はい | はい | はい | いいえ | いいえ |
| ビジュアルベーシック.NET | はい | はい | はい | はい | はい | いいえ | いいえ |
| Windows PowerShell | いいえ | はい | はい | フォールスルー | はい | いいえ | いいえ |
else ifcase構文では、正規表現マッチングは条件付きフロー制御の選択肢の一つです。例として、こちらの質問をご覧ください。CASECASEWHENcond1THENexpr1WHENcond2THENexpr2[...]ELSEexprDfltENDif ... else if ... elseCASECASEexprWHENval1THENexpr1[...]ELSEexprDfltENDMERGE組み込み関数が追加されました。Fortran 2023 では C のような三項演算子が追加されました。ifFortran 90 では廃止予定とされていました。Fortran 2018 標準では削除されました。記号表:「太字
else if
」→「
elif
」;「簡略
else if
」→「
|:
」)