(defmacro scase (keyform &rest clauses) "Variant of CASE with equality checked using STRING= instead of EQL." (let ((kfsym (gensym))) (flet ((map-clause (rest-of-clauses) (cond ((null (car rest-of-clauses)) (error "Invalid scase clause: ~A" (car rest-of-clauses))) ((and (null (cdr rest-of-clauses)) ; last clause (not (consp (caar rest-of-clauses))) (member (caar rest-of-clauses) '(otherwise t) :test #'string=)) (cons t (cdar rest-of-clauses))) (t (let* ((clause (car rest-of-clauses)) (keys (car clause)) (body (cdr clause))) (if (consp keys) (cons `(member ,kfsym ',keys :test #'string=) body) (cons `(string= ,kfsym ,keys) body))))))) `(let ((,kfsym ,keyform)) ,(cons 'cond (maplist #'map-clause clauses))))))