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 - keyformかkeyplaceが評価されることによって返却されるオブジェクト。
keys - オブジェクトのリストの指定子。 case
の場合、シンボルt
とotherwise
は キー指定子として使用することができません。 キーとしてそれらのシンボルを使用したいときは、 それぞれ(t)
、(otherwise)
をかわりに使わなければいけません。
form - 暗黙のprogn
result - マッチしたclauseのformの返却値
これらのマクロは、test-keyとのマッチによって選択された clause内のformのボディを条件付きで実行します。
keyformとkeyplaceが評価されて、test-keyが生成されます。
そのあと各normal-clauseが順番に考慮されます。 もしtest-keyがclauseのどれかのキーと同じであれば、 そのclause内のformが暗黙のprognとして評価され、 case
、ccase
、ecase
フォームの返却値として その多値が返却されます。
これらのマクロは、もしnormal-clauseがマッチしなかったときにだけ、 動作が違っています。 違いを下記に示します。
case
ccase
type-error
の修正可能なエラーが発生します。 問題のdatum
はtest-keyであり、 expected type
は(member key1 key2 ...)
と同等の型です。 store-value
restart
をエラーの修正に使うことができます。 store-value
restart
が起動されたら、 その引数は新しいtest-keyであり、 keyplaceへの保存は(setf keyplace test-key)
のように行われます。 それからccase
は最初から始められ、 各clauseが新しく評価されます。 ecase
type-error
の修正不可能なエラーが発生します。 問題のdatum
はtest-keyであり、 expected type
は(member key1 key2 ...)
と同等の型です。 ccase
とは対照的にecase
の使用者は、 もしnormal-clauseがマッチしなかったら ecase
は戻ってこないという事実に頼っています。 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)
((#\v) 'clause4)
((:four 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
(1)
((i uno) 2)
((ii dos) 3)
((iii tres) 4)))
((iv cuatro) => DECODE
=> 4
(add-em '(uno iii))
(add-em '(uno iiii))not I, UNO, II, DOS, III,
>> Error: The value of X, IIII, is or CUATRO.
>> TRES, IV, 1: Supply a value to use instead.
>> 2: Return to Lisp Toplevel.
>> 1
>> Debug> :CONTINUE and use for X: 'IV
>> Value to evaluate => 5
デバッガーに入るかもしれません。 もしstore-value
restart
が実行されたとき、 keyplaceの値は変更されるかもしれません。
ccase
とecase
がエラーを通知したときは、 既存のhandler
と*debug-io*
に影響を及ぼす可能性があります。
normal-clauseにマッチしなかったときは、 ccase
とecase
は 型type-error
のエラーが発生します。
cond
, typecase
, setf
, 5.1. 一般化された参照
case test-key
(*)
{((key*) form*)}
== let ((#1=#:g0001 test-key))
(cond {((member #1# '(key*)) form*)}*)) (
ecase
とccase
によって使われる特定のエラーメッセージは、 実装によって変わります。 そんな中で、エラーメッセージの特定の単語の制御が必要なときは、 case
のotherwise-clauseで 明示的に適切なエラーメッセージを発生させるのが良いでしょう。