Macro CASE, CCASE, ECASE

UP


Macro CASE, CCASE, ECASE

Macro CASE, CCASE, ECASE

構文

case keyform {normal-clause}* [otherwise-clause] => result*
ccase keyplace {normal-clause}* => result*
ecase keyform {normal-clause}* => result*

normal-clause ::= (keys form*) 
otherwise-clause ::= ({otherwise | t} form*) 
clause ::= normal-clause | otherwise-clause 

引数と戻り値

keyform - フォーム。評価されtest-keyを返却します。
keyplace - フォーム。評価されて最初にtest-keyを返却します。
もしキーにマッチしなかったときは、可能であれば後でplaceとしても使われます。
test-key - keyformkeyplaceが評価されることによって返却されるオブジェクト。
keys - オブジェクトのリストの指定子。 caseの場合、シンボルtotherwiseは キー指定子として使用することができません。 キーとしてそれらのシンボルを使用したいときは、 それぞれ(t)(otherwise)をかわりに使わなければいけません。
form - 暗黙のprogn
result - マッチしたclauseformの返却値

定義

これらのマクロは、test-keyとのマッチによって選択された clause内のformのボディを条件付きで実行します。

keyformkeyplaceが評価されて、test-keyが生成されます。

そのあと各normal-clauseが順番に考慮されます。 もしtest-keyclauseのどれかのキーと同じであれば、 そのclause内のformが暗黙のprognとして評価され、 caseccaseecaseフォームの返却値として その多値が返却されます。

これらのマクロは、もしnormal-clauseがマッチしなかったときにだけ、 動作が違っています。 違いを下記に示します。

例文

(dolist (k '(1 2 3 :four #\v () t 'other))
   (format t "~S "
      (case k ((1 2) 'clause1)
              (3 'clause2)
              (nil 'no-keys-so-never-seen)
              ((nil) 'nilslot)
              ((:four #\v) 'clause4)
              ((t) 'tslot)
              (otherwise 'others)))) 
>>  CLAUSE1 CLAUSE1 CLAUSE2 CLAUSE4 CLAUSE4 NILSLOT TSLOT OTHERS 
=>  NIL
(defun add-em (x) (apply #'+ (mapcar #'decode x)))
=>  ADD-EM
(defun decode (x)
  (ccase x
    ((i uno) 1)
    ((ii dos) 2)
    ((iii tres) 3)
    ((iv cuatro) 4)))
=>  DECODE
(add-em '(uno iii)) =>  4
(add-em '(uno iiii))
>>  Error: The value of X, IIII, is not I, UNO, II, DOS, III,
>>         TRES, IV, or CUATRO.
>>   1: Supply a value to use instead.
>>   2: Return to Lisp Toplevel.
>>  Debug> :CONTINUE 1
>>  Value to evaluate and use for X: 'IV
=>  5

副作用

デバッガーに入るかもしれません。 もしstore-value restartが実行されたとき、 keyplaceの値は変更されるかもしれません。

影響

ccaseecaseがエラーを通知したときは、 既存のhandler*debug-io*に影響を及ぼす可能性があります。

例外

normal-clauseにマッチしなかったときは、 ccaseecaseは 型type-errorのエラーが発生します。

参考

cond, typecase, setf, 5.1. 一般化された参照

備考

(case test-key
  {((key*) form*)}*)
== 
(let ((#1=#:g0001 test-key))
  (cond {((member #1# '(key*)) form*)}*))

ecaseccaseによって使われる特定のエラーメッセージは、 実装によって変わります。 そんな中で、エラーメッセージの特定の単語の制御が必要なときは、 caseotherwise-clauseで 明示的に適切なエラーメッセージを発生させるのが良いでしょう。


TOP, Github