コンピュータプログラミングにおいて、ガードとは、プログラムの実行が該当する分岐に進むために真と評価されなければならないブール式のことです。使用するプログラミング言語に関わらず、ガード句、ガードコード、またはガード文は、実行中のエラーを回避するために使用される整合性の前提条件のチェックです。
ガード句とは、ソフトウェア設計パターンの一種で、ケント・ベックが考案したもので、彼はこれまで名前のなかった多くのコーディング手法を体系化し、ソフトウェア設計パターンとして確立しました。この手法の使用は、少なくとも1960年代初頭にまで遡ります。ガード句は、通常、プロシージャの冒頭に追加され、エッジケースを事前に処理することで、プロシージャの残りの部分を「保護」すると言われています。
典型的な例としては、処理しようとしている参照がnullでないことを確認することで、 nullポインタエラーを回避することが挙げられます。
その他の用途としては、 dispose パターンのように、冪等性 のためにブール型フィールドを使用する(後続の呼び出しはnopになる)などがあります。
public String foo ( String username ) { if ( username == null ) { throw new IllegalArgumentException ( "ユーザー名が null です。" ); }// メソッドの残りのコードはここに続きます... }ガードはサブルーチンからの早期終了を提供し、構造化プログラミングからの一般的な逸脱であり、1 レベルのネストを削除してよりフラットなコードをもたらします: [ 1 ]を に置き換えます。if guard { ... }if not guard: return; ...
ガード句を使うことは、コードを改善するためのリファクタリング手法の一つです。一般的に、ネストが少ないほどコードが簡素化され、理解の負担が軽減されるため、好ましいと言えます。
例えば、Pythonでは:
from typing import Any , Optional# この関数にはガード句がありませんdef f_noguard ( x : Any ) -> Optional [ int ] if isinstance ( x , int ): # ここにコードを記述return x + 1 else : return None# ガード句を持つ同等の関数。コードの大部分はインデントが少ないため、読みやすく、理解しやすくなっています。def f_guard ( x : Any ) -> Optional [ int ] if not isinstance ( x , int ): return None # ここにコードを記述return x + 1別の例として、C言語で書かれたもの:
// この関数にはガード句がありませんint funcNoGuard ( int x ) { if ( x >= 0 ) { // ここにコードを記述return x + 1 ; } else { return 0 ; } }// ガード句を持つ同等の関数int funcGuard ( int x ) { if ( x < 0 ) { return 0 ; }// ここにコードを記述 return x + 1 ; }この用語は、 APL、Haskell、Clean、Erlang、occam、Promela、OCaml、Swift、[ 2 ] Python(バージョン3.10以降)、およびScalaプログラミング言語で特定の意味で使用されます。Mathematicaでは、ガードは制約と呼ばれます。ガードは、形式手法の言語であるGuarded Command Languageの基本概念です。ガードを使用すると、構造が一致する場合でもパターンをスキップできる可能性でパターンマッチングを拡張できます。条件文のブール式も、条件と呼ばれますが、通常はこのガードの定義に当てはまります。
以下の Haskell の例では、ガードは「|」と「="」の各ペアの間にあります。
f x | x > 0 = 1 |それ以外の場合= 0これは、それぞれの数学的表記法に似ています。
この場合、ガードは「if」節と「otherwise」節の中にあります。
並列ガードが複数ある場合、通常は上から下の順に試行され、最初に合格したガードの分岐が選択されます。ケースのリスト内のガードは、通常並列です。
しかし、Haskellのリスト内包表記では、ガードは直列に配置され、いずれかのガードが失敗した場合、リスト要素は生成されません。これは、個々のガードを論理ANDで結合するのとほぼ同じですが、ガードの間に他のリスト内包表記句が存在する可能性がある点が異なります。
1963年のCPLに既に存在していた単純な条件式は、最初の部分式にガードがあり、最初の部分式が使用できない場合に使用する別の部分式があります。これを記述する一般的な方法をいくつか示します。
(x>0) -> 1/x; 0 x>0 ? 1/x : 0
2番目の部分式がさらに単純な条件式である場合、最後のフォールスルーの前に試せる選択肢を増やすことができます。
(x>0) -> 1/x; (x<0) -> -1/x; 0
1966年のISWIMには、必須のフォールスルーケースを持たない条件式があり、ガードと二者択一の概念を分離していた。ISWIMの場合、いずれの選択肢も使用できない場合は、値は未定義となり、決して値に計算されないことが定義されていた。
KRCは、 SASL (1976年)の「小型版」[ 3 ]であり、「ガード」という用語を使用した最初のプログラミング言語の1つでした。その関数定義には複数の節を含めることができ、各節に続くガードに基づいて適用する節が選択されました。
fac n = 1 、n = 0 = n * fac ( n - 1 )、n > 0ガード句の使用、および「ガード句」という用語は、少なくとも1990年代のSmalltalkの実践にまで遡り、 Kent Beckによって体系化されている。[ 1 ]
1996年、Dyalog APLは、ガードが唯一の制御構造である代替的な純粋関数型スタイルを採用した。[ 4 ]このAPLの例は、入力された数値の偶奇性を計算する。
パリティ← { 2 ∣ ⍵ : '奇数' '偶数' }パターンに付随するガードに加えて、パターンガードはガードのコンテキストにおけるパターンマッチングの使用を指す場合もあります。実際には、パターンの一致はパスとみなされます。この意味は、1997年4月にサイモン・ペイトン・ジョーンズがHaskell向けに発表した「ガードの新しい見方」という提案で導入され、その提案の実装で使用されました。この機能により、パターンのガード内でパターンを使用できるようになります。
拡張Haskellの例:
clunky env var1 var2 | Just val1 <- lookup env var1 , Just val2 <- lookup env var2 = val1 + val2 -- ...clunky の他の方程式...これは次のように読み取れます。「環境と 2 つの変数に対して扱いにくいですが、環境からの変数のルックアップによって値が生成された場合、それは値の合計です。...」リスト内包表記と同様に、ガードは直列に配置され、いずれかのガードが失敗した場合は分岐が実行されません。