ガード (プログラミング)

ガード (Guard) とは、コンピュータ・プログラミング言語において、条件式ないし条件分岐のような意味を持つもので、ある分岐で処理を続けるために真 (true) と評価されなければならない[1]である。偽の場合は残りの処理のほうに進む。パターンマッチングのある言語の、パターンマッチングの能力をより強化したものと見ることもできる。すなわち、パターンマッチングとして構造がマッチしていても、その構造の中身の値を評価した結果によってはスキップさせることが可能なパターンのようなもの、である。

[編集]

以下の Haskell のコード例で、"|" と "=" の間の部分がガードである。

 f x    | x > 0     = 1    | otherwise = 0 

これは、以下のような、数学で使われる記法に似ている。

この場合、ガードは "if"節と "otherwise"節にある。

上記の例のように複数のガードがある場合、先頭から順に評価され、最初に真となった分岐が選択される。

Haskell のリスト内包表記でのガード列は、1つでも偽であった場合にそのリスト要素が生成されない。これはつまり、個々のガードを論理積で結合したと見なすことができるが、リスト内包表記にはガード以外も列挙される。

言語

[編集]

ガードのような機能を持つ言語として、HaskellCleanErlangoccamOCamlといったプログラミング言語や多くの並行論理プログラミング言語が挙げられる。Mathematicaではガードをconstraintと呼ぶ。形式手法の言語であるGuarded Command Language(詳細は歴史の節で後述)でも重要な構成要素である。

パターンガード

[編集]

パターンガードとは、ガード内でパターンマッチングを行うこと(あるいはそのようなガード)である。この定義は Haskell についてサイモン・ペイトン・ジョーンズA new view of guards として1997年4月に提案し、その後実装されている。

Haskell での例を示す。

 clunky env var1 var2    | Just val1 <- lookup env var1    , Just val2 <- lookup env var2    = val1 + val2  ...other equations for clunky... 

ここで、"<-" はパターンガード修飾子と呼ばれ、右辺を評価した結果を左辺とパターンマッチする。リスト内包表記のようにパターンガードを並べることができ、いずれかがパターンマッチに失敗すれば、その分岐は実行されない。

歴史

[編集]

頭部に書かれた式(条件式)を評価した真偽にもとづき、最初に真になった所の対応する本体を評価した値を全体の結果とする、というような記法はプログラミング言語以前に数学で使われており、Haskellのものなどは以下の歴史よりも、むしろ数学における記法をそのまま取り入れたものに近い。1960年の「Lispの論文」と呼ばれるRecursive Functions of Symbolic Expressions and Their Computation by Machine, Part Iマッカーシー)で導入された、

(p1 → e1, ・・・, pn → en) 

という記法もその一種と言え、その後のLispではS式による記法が一般的になったものの、それでもLispの、ifではなくcondによる条件式はこれに近い。

1963年のCPLストレイチー他)にも似たものが存在しており、最初の部分式に対するガードが記述され、その後にガードが偽であった場合の部分式が記述される。例えば以下のように記述される。

(x>0) -> 1/x; 0 x>0 ? 1/x : 0 

後半の部分式も条件付きの式として記述できる場合、以下のような記述が可能となる。

(x>0) -> 1/x; (x<0) -> -1/x; 0 

1966年のISWIM(Landin(en:Peter Landin))では既に else 節に相当する部分のない条件付き式があり、ガードと二者択一の概念が分離されている。ISWIM では、どの分岐も真でない場合、全体として式の値は「未定義」とされ、値が計算されないと定義されていた。

プログラミング言語というよりは理論寄りで提案されたものだが、1975年[2]Guarded Command LanguageダイクストラEWD472)もガードを多用する言語である。文献から引用すると、たとえば、xとyの最大値をmに求める記述はifとガードを使って、

if   x ≥ y → m:= x    ▯ y ≥ x → m:= y fi . 

となる。さらに、繰返し評価を行うdoは次のような記法で、

do   ql > q2 → ql, q2 := q2, ql    ▯ q2 > q3 → q2, q3 := q3, q2    ▯ q3 > q4 → q3, q4 := q4, q3 od . 

いずれかの条件が成立する限り繰り返す(ifの場合と違い、doでは複数の条件が成立した場合はいずれかが選ばれる)。

1976年のSASL(en:SASL (programming language)[3], en:David Turner (computer scientist))は「ガード」という用語を使った初期のプログラミング言語の1つであり、関数の定義を複数持たせて、ガードによって適用する定義を選択するようになっていた。これは細かい表面上の違いを除けば、後のHaskellにおける記法のガードの位置を後ろにもってきたようなものであり、あるいはHaskellのそれ以上に数学における記法に似ている。

fac n = 1,             n = 0       = n * fac (n-1), n > 0 

1980年代のGuarded Horn Clauses(上田)もガードを多用する言語である。

参考文献

[編集]

[編集]
  1. ^ ないし、真 (true) として扱われる値(言語により異なる)でなければならない
  2. ^ Dijkstra, E.W.: Guarded commands, nondeterminacy and formal derivation of programs. Commun. ACM 18 (1975), 8: 453–457.
  3. ^ 初出は1972年となっているが、何度か更新している。