実装終わってから名前の不味さに気付いた。これじゃあまるで大文字小文字の操作関数だ。
それはそうと、これは使い道があまり無いね。
元の話題のような、本当の書き捨てなら cond で string= を手書きした方が早い。
それなりの規模のコードで本格的に使いたいなら、特定の述語に特化したマクロを単品で使うよりも適切なライブラリを探してきた方が良い。
(defmacro string-case (key-string &rest clauses)
(unless (stringp key-string)
(error "~¬ string key specified: ~a" key-string) )
(with-gensyms (#+clisp "" key)
`(let ((,key ,key-string))
(cond ,@(string-case-clause-expander key t clauses)) )))
(defmacro string-ecase (key-string &rest clauses)
(unless (stringp key-string)
(error "~¬ string key specified: ~a" key-string) )
(with-gensyms (#+clisp "" key)
`(let ((,key ,key-string))
(cond ,@(string-case-clause-expander key nil clauses)
(t (error "the value of ~s must be one of case conditions"
,key-string )) ))))
(defun string-case-clause-expander (key accept-otherwise clauses)
(mapcar (lambda (clause)
(string-case-clause-condition-expander
key accept-otherwise clause ))
clauses ))
(defun string-case-clause-condition-expander (key accept-otherwise clause)
(destructuring-bind (condition &body body) clause
`(,(cond ((null condition) nil)
((stringp condition) `(string= ,condition ,key))
((listp condition)
`(or ,@(mapcar (lambda (elm) `(string= ,elm ,key)) condition)) )
((and accept-otherwise
(symbolp condition)
(string= (symbol-name condition) "otherwise") )
t )
(t (error "~a: invalid case condition: ~a"
(if accept-otherwise 'string-case 'string-ecase)
condition )) )
,@body )))