1

次の case ステートメントでは、x が #\j に設定されていますが、"bye" が返されます。

(case (find #\j "joy") ((x) (princ "hi")) (otherwise (princ "bye")))

find は #\j を返すはずですが、これは x と一致するはずですよね?

4

2 に答える 2

5

みてみましょう。

CL-USER 2 > (setf x #\j)
#\j

CL-USER 3 > (case (find #\j "joy") ((x) (princ "hi")) (otherwise (princ "bye")))
bye
"bye"

単純化: を取り除きましょうFIND

CL-USER 4 > (case #\j ((x) (princ "hi")) (otherwise (princ "bye")))
bye
"bye"

動作しません。単純化: しないでくださいPRINC

CL-USER 5 > (case #\j ((x) (princ "hi")) (otherwise "bye"))
"bye"

動作しません。単純化: しないでくださいPRINC

CL-USER 6 > (case #\j ((x) "hi") (otherwise "bye"))
"bye"

動作しません。小さな表現があります。CASEマクロです。フォームを展開してみましょう:

CL-USER 7 > (macroexpand '(case #\j ((x) "hi") (otherwise "bye")))
(LET ((#:G1084 #\j))
  (COND ((OR (EQL (QUOTE X) #:G1084)) "hi")
        (T "bye")))
T

ああ、X引用され、評価されていません。したがって、文字#\jが記号と等しいかどうかをテストしていますX。これは失敗します。

CASEキーを評価しません。

解決策: のようなものを使用するか、 のようなCONDものを隠すマクロを作成しCONDます。これは演習として何度も書いています。

CL-USER 8 > (let ((value (find #\j "joy")))
              (cond ((eql value x) "hi")
                    (t "bye")))
"hi"
于 2013-01-11T08:49:46.983 に答える
3

句キーは評価されないため、句((x)...)は記号と一致しますxこれがケースの要点です。キーは一定であるため、フォームをコンパイルしてより効率的なコードを生成できます。動的キーが必要な場合は、関連付けリスト、ハッシュテーブルなどを使用します。

于 2013-01-11T07:04:39.157 に答える