【发布时间】:2014-01-05 12:03:33
【问题描述】:
我想知道 case 宏是如何工作的,但仅仅扩展它是不够的。它如何在不知道有多少参数的情况下生成 cond 语句?它是否使用循环或其他东西?如果是这样,为什么我运行宏扩展时它不显示。
我需要写一些以类似方式工作的东西,这就是我问的原因。
【问题讨论】:
-
为什么不查看您最喜欢的实现的源代码?
我想知道 case 宏是如何工作的,但仅仅扩展它是不够的。它如何在不知道有多少参数的情况下生成 cond 语句?它是否使用循环或其他东西?如果是这样,为什么我运行宏扩展时它不显示。
我需要写一些以类似方式工作的东西,这就是我问的原因。
【问题讨论】:
是的,您需要使用迭代 - loop、do、mapcar &c 之一(或递归)。
看一下,例如CLISP's implementation of case:
(defun case-expand (whole-form form-name test keyform clauses)
(let ((var (gensym (string-concat (symbol-name form-name) "-KEY-"))))
`(let ((,var ,keyform))
(cond
,@(maplist
#'(lambda (remaining-clauses)
(let ((clause (first remaining-clauses))
(remaining-clauses (rest remaining-clauses)))
(unless (consp clause)
(error-of-type 'source-program-error
:form whole-form
:detail clause
(TEXT "~S: missing key list")
form-name))
(let ((keys (first clause)))
`(,(cond ((or (eq keys 'T) (eq keys 'OTHERWISE))
(if remaining-clauses
(error-of-type 'source-program-error
:form whole-form
:detail clause
(TEXT "~S: the ~S clause must be the last one")
form-name keys)
't))
((listp keys)
`(or ,@(mapcar #'(lambda (key)
`(,test ,var ',key))
keys)))
(t `(,test ,var ',keys)))
,@(rest clause)))))
clauses)))))
(defmacro case (&whole whole-form
keyform &body clauses)
(case-expand whole-form 'case 'eql keyform clauses))
【讨论】:
case 可以扩展为一个 if,它检查第一个案例并将 else 部分保留为 (case ...)。宏定义不会显式递归。