Macro TYPECASE, CTYPECASE, ETYPECASE

UP


Macro TYPECASE, CTYPECASE, ETYPECASE

Function TYPECASE, CTYPECASE, ETYPECASE

構文

typecase keyform {normal-clause}* [otherwise-clause] => result*
ctypecase keyplace {normal-clause}* => result*
etypecase keyform {normal-clause}* => result*

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

引数と戻り値

keyform - フォーム。評価されtest-keyを返却します。
keyplace - フォーム。評価されて最初にtest-keyを返却します。
test-key - keyformkeyplaceが評価されることによって返却されるオブジェクト。
type - 型指定子
form - 暗黙のprogn
result - マッチしたclauseformの返却値

定義

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

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

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

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

3つの全ての場合において、 指定した型にマッチするclauseが複数あっても許されます。 特にその型が何かのサブタイプになっているような場合も同様です。 そのような場合は、もっとも早い適切なclauseが選ばれます。

例文

;;; (この例で使われているTYPE-OFの部分は
;;;  実装依存であることに注意して下さい)
(defun what-is-it (x)
  (format t "~&~S is ~A.~%"
          x (typecase x
              (float "a float")
              (null "a symbol, boolean false, or the empty list")
              (list "a list")
              (t (format nil "a(n) ~(~A~)" (type-of x))))))
=>  WHAT-IS-IT
(map 'nil #'what-is-it '(nil (a b) 7.0 7 box))
>>  NIL is a symbol, boolean false, or the empty list.
>>  (A B) is a list.
>>  7.0 is a float.
>>  7 is a(n) integer.
>>  BOX is a(n) symbol.
=>  NIL
(setq x 1/3)
=>  1/3
(ctypecase x
    (integer (* x 4))
    (symbol  (symbol-value x)))
>>  Error: The value of X, 1/3, is neither an integer nor a symbol.
>>  To continue, type :CONTINUE followed by an option number:
>>   1: Specify a value to use instead.
>>   2: Return to Lisp Toplevel.
>>  Debug> :CONTINUE 1
>>  Use value: 3.7
>>  Error: The value of X, 3.7, is neither an integer nor a symbol.
>>  To continue, type :CONTINUE followed by an option number:
>>   1: Specify a value to use instead.
>>   2: Return to Lisp Toplevel.
>>  Debug> :CONTINUE 1
>>  Use value: 12
=>  48
x =>  12

影響

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

例外

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

もしあるclauseがそれより早いclauseによって完全にシャドウされ、 決して選択されないような状況であったとき、 コンパイラーは、型style-warningの警告を出すかどうか 選択することができます。

参考

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

備考

(typecase test-key
  {(type form*)}*)
== 
(let ((#1=#:g0001 test-key))
  (cond {((typep #1# 'type) form*)}*))

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


TOP, Github