Next: Combining Conditions, Previous: Sequencing, Up: Control Structures [Contents][Index]
条件による制御構造は候補の中から選択を行ないます。Emacs
Lispは5つの条件フォームをもちます。if
は他の言語のものとほとんど同じです。when
とunless
はif
の変種です。cond
は一般化されたcase命令です。cond
を汎用化したものがpcase
です(Pattern-Matching Conditionalを参照)。
if
はconditionの値にもとづきthen-formとelse-formsを選択する。評価されたconditionが非nil
ならthen-formが評価されて結果がリターンされる。それ以外ならelse-formsがテキスト順に評価されて最後のフォームの値がリターンされる(if
のelseパートは暗黙のprogn
の例である。Sequencingを参照)。
conditionの値がnil
でelse-formsが与えられなければ、if
はnil
をリターンする。
選択されなかったブランチは決して評価されない — 無視される —
ので、if
はスペシャルフォームである。したがって以下の例ではprint
が呼び出されることはないのでtrue
はプリントされない。
(if nil (print 'true) 'very-false) ⇒ very-false
これはelse-formsがなく、複数のthen-formsが可能なif
の変種である。特に、
(when condition a b c)
は以下と完全に等価である
(if condition (progn a b c) nil)
これはthen-formがないif
の変種です:
(unless condition a b c)
は以下と完全に等価である
(if condition nil a b c)
cond
は任意個数の選択肢から選択を行なう。cond
内の各clauseはリストでなければならない。このリストのCARはconditionで、(もしあれば)残りの要素はbody-formsとなる。したがってclauseは以下のようになる:
(condition body-forms…)
cond
は各clauseのconditionを評価することにより、テキスト順でclauseを試みる。conditionの値が非nil
ならそのclauseは成り立つ。その後にcond
はそのclauseのbody-formsを評価して、body-formsの最後の値をリターンする。残りのclauseは無視される。
conditionの値がnil
ならそのclauseは失敗して、cond
は次のclauseに移動してそれのconditionを試みる。
clauseは以下のようにも見えるかもしれない:
(condition)
conditionがテストされたときに非nil
なら、cond
フォームはconditionの値をリターンする。
すべてのconditionがnil
に評価された場合 —
つまりすべてのclauseが不成立なら、cond
はnil
をリターンする。
以下の例はx
の値が数字、文字列、バッファー、シンボルなのかをテストする4つのclauseをもつ:
(cond ((numberp x) x) ((stringp x) x) ((bufferp x) (setq temporary-hack x) ; 1つのclauseに (buffer-name x)) ; 複数bodyフォーム ((symbolp x) (symbol-value x)))
前のclauseが不成立のとき最後の条項を実行したいときがよくある。これを行なうには(t
body-forms)
のように、conditionの最後のclauseにt
を使用する。フォームt
はt
に評価され決してnil
にならないので、このclauseが不成立になることはなく最終的にcond
はこのclauseに到達する。たとえば:
(setq a 5) (cond ((eq a 'hack) 'foo) (t "default")) ⇒ "default"
このcond
式はa
の値がhack
ならfoo
、それ以外は文字列"default"
をリターンする。
すべての条件構文はcond
かif
のいずれかで表すことができます。したがってどちらを選択するかはスタイルの問題になります。たとえば:
(if a b c) ≡ (cond (a b) (t c))