如何在lisp中实现defun宏?

时间:2017-02-26 16:17:19

标签: macros lisp common-lisp clisp

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

2 个答案:

答案 0 :(得分:8)

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

  1. 228
  2. 1789
  3. 1946
  4. defun的基本定义可能是:

    defun

    事实上,这是CLISP中(defmacro defun (fname lambda-list &rest body) `(setf (fdefinition ',fname) (lambda ,lambda-list (block ,fname ,@body)))) 的第一个定义(第228行),除了当时没有defmacro且没有backquote 但是,所以实际的代码看起来很丑陋。

    另请参阅Is defun or setf preferred for creating function definitions in common lisp and why?我在哪里讨论defun s的宏扩展。

答案 1 :(得分:0)

您可以通过运行

轻松检查特定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中搜索,因为大多数实现都是开源的。

BTW defun并不那么特别。你可以用setf - inf symbol-function来实现lambda的大部分内容。 E.g:

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