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