【问题标题】:Lisp - "case" macro implementationLisp - “case”宏实现
【发布时间】:2014-01-05 12:03:33
【问题描述】:

我想知道 case 宏是如何工作的,但仅仅扩展它是不够的。它如何在不知道有多少参数的情况下生成 cond 语句?它是否使用循环或其他东西?如果是这样,为什么我运行宏扩展时它不显示。

我需要写一些以类似方式工作的东西,这就是我问的原因。

【问题讨论】:

  • 为什么不查看您最喜欢的实现的源代码?

标签: macros lisp


【解决方案1】:

是的,您需要使用迭代 - loopdomapcar &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 ...)。宏定义不会显式递归。
猜你喜欢
  • 1970-01-01
  • 2011-03-28
  • 2012-04-06
  • 2017-07-17
  • 2013-05-06
  • 2014-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多