12

McCarthy 的基本 S-函数和谓词是atom, eq, car, cdr,cons

然后,他继续添加到他的基本符号,以便能够编写他所谓的 S-Function:quote, cond, lambda,label

在此基础上,我们将这些称为“LISP 原语”(尽管我对关于类型谓词的争论持开放态度,例如numberp

您将如何defmacro在您选择的 LISP 中仅使用这些原语来定义函数?(包括 Scheme 和 Clojure)

4

2 回答 2

6

尝试在像 McCarthy 的 LISP 机器这样的机器上执行此操作的问题在于,没有办法防止在运行时进行参数评估,也没有办法在编译时改变事情(这就是宏所做的:它们重新排列代码在编译之前,基本上)。

但这并不能阻止我们在运行时在 McCarthy 的机器上重写我们的代码。诀窍是引用我们传递给“宏”的参数,这样它们就不会被评估。

作为一个例子,让我们看一个我们可能想要的函数;unless. 我们的理论函数有两个参数,pand q,并且返回q ,除非 p为真。如果p为真,则返回 nil。

一些例子(在 Clojure 的语法中,但这并没有改变任何东西):

(unless (= "apples" "oranges") "bacon")
=> "bacon"

(unless (= "pears" "pears") "bacon")
=> nil

所以一开始我们可能想写成unless一个函数:

(defn unless [p q]
    (cond p nil
          true q))

这似乎工作得很好:

(unless true 6)
=> nil

(unless false 6)
=> 6

使用 McCarthy 的 LISP,它可以正常工作。问题是我们在现代 Lisps 中不仅有无副作用的代码,因此传递给的所有参数unless都被评估,无论我们是否想要它们,这一事实是有问题的。事实上,即使在 McCarthy 的 LISP 中,如果评估其中一个论点需要很长时间才能完成,而我们只想很少这样做,这也可能是一个问题。但这尤其是一个副作用问题。

所以我们希望我们在为假unless时评估和返回。如果我们将和作为参数传递给函数,我们就无法做到这一点。q pqp

但是我们可以quote在将它们传递给我们的函数之前对其进行处理,从而阻止它们的评估。我们可以使用eval(也定义了,仅使用原语和其他在参考论文后面的原语中定义的函数)的力量来评估我们需要什么,什么时候需要。

所以我们有一个新的unless

(defn unless [p q] 
    (cond (eval p) nil 
          true (eval q)))

我们使用它有点不同:

(unless (quote false) (quote (println "squid!")))
=> "squid" nil
(unless (quote true) (quote (println "squid!")))
=> nil

在那里你有一个可以慷慨地称为宏的东西。


但这不是defmacro或其他语言中的等价物。那是因为在 McCarthy 的机器上,没有办法在编译时执行代码。而且,如果您正在使用该eval函数评估您的代码,它就无法知道不评估“宏”函数的参数。阅读和评估之间的区别与现在不同,尽管想法就在那里。“重写”代码的能力是存在的,在与quote结合的酷和列表操作中eval,但它并没有像现在这样被保留在语言中(我几乎称它为语法糖:只需引用你的论点,你就有了宏观系统的力量。)

我希望我已经回答了你的问题,而不是试图defmacro用这些原语来定义一个体面的东西。如果您真的想看到这一点,我会向您指出 Clojure 源代码中难以理解的defmacro代码,或者 Google 更多。

于 2010-08-21T04:39:08.503 回答
2

在这里完整地解释它的所有细节需要大量的空间和时间来回答,但大纲真的很简单。每个 LISP 最终在其核心中都有类似于 READ-EVAL-PRINT 循环的东西,也就是说,它需要一个列表,一个元素一个元素,解释它,并改变状态——无论是在内存中还是通过打印结果。

读取部分查看读取的每个元素并对其进行处理:

(cond ((atom elem)(lambda ...))
      ((function-p elem) (lambda ...)))

要解释宏,您只需 (?) 需要实现一个函数,将宏的模板文本放在存储中的某个位置,该 repl 循环的谓词——这意味着简单地定义一个函数——它说“哦,这是一个宏!”,然后将该模板文本复制回阅读器,以便对其进行解释。

如果您真的想了解细节,请阅读计算机程序的结构和解释 或阅读 Queinnec 的Lisp in Small Pieces

于 2010-08-21T04:20:29.580 回答