【问题标题】:How is the defun macro implemented in lisp?lisp中的defun宏是如何实现的?
【发布时间】:2017-07-17 04:36:42
【问题描述】:

我想了解有关 lisp 宏的更多信息,并且我想创建一个 defun 宏的简单实现。 我对所有实现中的lisp源代码也很感兴趣。

【问题讨论】:

  • 为什么不自己检查一下,然后提出具体问题呢?您可以研究许多开源 Lisp 实现。如果你想了解 Lisp 宏,我会推荐 'On Lisp' - 那本书的免费 PDF:paulgraham.com/onlisp.html
  • 一开始不知道去哪里找。

标签: macros lisp common-lisp clisp


【解决方案1】:

您可以通过运行轻松检查您的特定 CL 实现是如何实现的,defun

(macroexpand '(defun add2 (x) (+ x 2)))

SBCL 上,它扩展为:

(PROGN
  (EVAL-WHEN (:COMPILE-TOPLEVEL) (SB-C:%COMPILER-DEFUN 'ADD2 NIL T))
  (SB-IMPL::%DEFUN 'ADD2
                   (SB-INT:NAMED-LAMBDA ADD2
                       (X)
                     (BLOCK ADD2 (+ X 2)))
                   (SB-C:SOURCE-LOCATION)))
T

要查看实现的特定源代码,我将使用(在 Emacs 上)M-. 键绑定,然后我将编写 defun 并按 Enter。然后 Emacs 会得到源代码:

(sb!xc:defmacro defun (&environment env name lambda-list &body body)
  #!+sb-doc
  "Define a function at top level."
[...]

我不打算粘贴整个宏,因为它很长。如果你不在 Emacs 上,你可以尝试在 repos 中搜索,因为大多数实现都是开源的。

顺便说一句,defun 并没有那么特别。您可以使用 setf-inf 和 symbol-function 到 lambda 来实现大部分功能。例如:

(setf (symbol-function 'ADD3) #'(lambda (x) (+ x 3)))
; => #<FUNCTION (LAMBDA (X)) {1006E94EBB}>
(add3 4)
; => 7

【讨论】:

    【解决方案2】:

    这是一个棘手的问题,因为bootstrappingdefun 做了很多事情(iow,调用很多函数),但是要定义这些函数,需要一个有效的defun。因此在clisp/src/init.lisp 中有三个(3!)defun 的定义:在行

    1. 228
    2. 1789
    3. 1946

    defun 的基本定义可能是这样的:

    (defmacro defun (fname lambda-list &rest body)
      `(setf (fdefinition ',fname)
             (lambda ,lambda-list 
               (block ,fname ,@body))))
    

    其实这是defun在CLISP中的第一个定义(第228行),只不过当时没有defmacro也没有backquote,所以实际代码看起来丑多了。

    另请参阅Is defun or setf preferred for creating function definitions in common lisp and why?,其中我讨论了defuns 的宏扩展。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-06
      • 1970-01-01
      • 1970-01-01
      • 2011-03-28
      • 2013-05-28
      • 2012-04-06
      • 1970-01-01
      • 2014-09-03
      相关资源
      最近更新 更多