代码之家  ›  专栏  ›  技术社区  ›  hawkeye

仅使用LISP原语定义defmacro函数?

  •  11
  • hawkeye  · 技术社区  · 14 年前

    McCarthy's atom , eq , car , cdr , cons

    然后,他继续在基本符号中添加,以编写他所称的S函数: quote cond , lambda , label

    numberp )

    defmacro 在您选择的LISP中只使用这些原语的函数?(包括方案和Clojure)

    2 回复  |  直到 14 年前
        1
  •  5
  •   Isaac    14 年前

    在像McCarthy的LISP机器这样的机器上尝试这样做的问题是,没有办法阻止在运行时进行参数计算,也没有办法在编译时进行更改(宏就是这样做的:基本上,它们在编译之前重新排列代码)。

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

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

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

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

    所以一开始我们可能想写 除非 作为一个函数:

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

    这似乎很管用:

    (unless true 6)
    => nil
    
    (unless false 6)
    => 6
    

    有了麦卡锡的口齿不清,一切正常。问题是,在现代的Lisps中,我们不仅仅有没有副作用的代码,因此所有参数都传递给 无论我们是否希望他们接受评估,都是有问题的。事实上,即使是在麦卡锡的口齿不清的情况下,这可能是一个问题,如果,比方说,评估一个论点采取 我们只想很少做。但它的副作用尤其严重。

    所以我们想要 评估并返回 只有 如果 p 是假的。如果我们通过了就不能这样做 p 作为函数的参数。

    但我们可以 quote 在我们将其传递给我们的职能部门之前,阻止对其进行评估。我们可以利用 eval (也定义了,只使用原语和其他函数定义的原语后面的参考文件)来评估我们需要什么,当我们需要的时候。

    所以我们有一个新的 除非

    (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的机器上,没有一种在编译时执行代码的方法。如果你用 评估 函数,它不能不计算“宏”函数的参数。在阅读和评价之间并没有现在这样的区别,尽管这个想法是存在的。“重写”代码的能力就在那里,在 列表操作与 评估

    我希望我已经回答了你的问题,而不是试图定义一个体面的 定义宏 和那些原始人在一起。如果你真的想看的话,我会把你指给那些难以理解的人看 source for defmacro 在Clojure的源代码中,或者在Google上搜索更多。

        2
  •  2
  •   Charlie Martin    14 年前

    读取部分查看每个读取的元素并对其执行操作:

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

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

    计算机程序的结构与解释 Lisp in Small PIeces .