Next: , Previous: Sequencing, Up: Control Structures


9.2 条件付き実行

条件付き制御構造は、選択肢を選びます。 Emacs Lispには、4つの条件付きフォームがあります。 他の言語のものとほとんど同じififの変形であるwhenunless、 一般化したcase文であるcondです。

— Special Form: if condition then-form else-forms...

ifは、conditionをもとにして、 then-formelse-formsを選ぶ。 conditionnil以外に評価されると、 then-formを評価し、その結果を返す。 さもなければ、else-formsをテキスト上の順に評価し、 その最後のものの値を返す。 (ifelse部分は、暗黙のprognの例である。 see Sequencing。)

conditionが値nilであり、かつ、else-formsがないと、 ifnilを返す。

ifがスペシャルフォームであるのは、 選択しなかった分岐をけっして評価しないからである。 したがって、つぎの例では、 printはけっして呼ばれないためtrueは表示されない。

          (if nil
              (print 'true)
            'very-false)
           very-false
— Macro: when condition then-forms...

これはifの変形であり、else-formsがなく、 then-formsは複数のフォームでもよい。 特に、

          (when condition a b c)

は、つぎとまったく等価である。

          (if condition (progn a b c) nil)
— Macro: unless condition forms...

これはthen-formがないifの変形である。

          (unless condition a b c)

は、つぎとまったく等価である。

          (if condition nil
             a b c)
— Special Form: cond clause...

condは任意個数の選択肢から1つを選ぶ。 condの各節clauseはリストである必要がある。 このリストのcarcondition(条件)である。 残りの要素は、あれば、body-forms(本体フォーム)である。 つまり、各節はつぎのようになる。

          (condition body-forms...)

condは、各節のconditionを評価して、 各節をテキスト上の順に試す。 conditionの値がnil以外であれば、 その節は『成功』する。 そうすると、condはその節のbody-formsを評価し、 body-formsの最後の値がcondの値となる。 残りの節は無視する。

conditionの値がnilであると、 その節は『失敗』し、 condはつぎの節へ移りそのconditionを試す。

conditionnilに評価されると、 すべての節が失敗し、condnilを返す。

clauseは、つぎの形式でもよい。

          (condition)

この場合、conditionnil以外であると、 conditioncondフォームの値になる。

以下の例には4つの節があり、 xの値が、数、文字列、バッファ、シンボルかどうか調べる。

          (cond ((numberp x) x)
                ((stringp x) x)
                ((bufferp x)
          
          
                 (setq temporary-hack x) ; 1つの節に
                 (buffer-name x))        ; 複数個の本体フォーム
                ((symbolp x) (symbol-value x)))

最後の節を除くそれよりまえの節がどれも成功しないときには、 最後の節を実行したいことがしばしばある。 これを行うには、(t body-forms)のように 最後の節のconditiontを使う。 フォームttと評価され、けっしてnilではない。 そのため、condがこの節に達したときには、 この節が失敗することはない。

たとえば、つぎのとおり。

          (cond ((eq a 'hack) 'foo)
                (t "default"))
           "default"

この式は、aの値がhackのときにはfooを返し、 さもなければ文字列"default"を返すcondである。

任意の条件付き構造は、condifで表現できます。 したがって、どちらを使うかは好みの問題です。 たとえば、つぎのとおりです。

     (if a b c)
     ==
     (cond (a b) (t c))