How is the defun macro implemented in lisp?
Asked Answered
A

2

10

I'd like to learn more about lisp macros and I want to create a simple implementation of the defun macro. I'm also interested in lisp's source code in all the implementations.

Austerlitz answered 26/2, 2017 at 16:17 Comment(2)
Why not check it out yourself and then ask specific questions? There are many open source Lisp implementations you can study. If you want to learn about Lisp macros I would recommend 'On Lisp' - free PDF of that book : paulgraham.com/onlisp.htmlPolestar
At first I didn't know where to search.Austerlitz
N
12

This is a tricky question, because of bootstrapping: defun does a lot of things (iow, calls a lot of functions), but to define those functions one needs a working defun. Thus there are three(3!) definitions of defun in clisp/src/init.lisp: at lines

  1. 228
  2. 1789
  3. 1946

The very basic definition of defun could be this:

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

In fact, this is the first definition of defun in CLISP (line 228), except that there is no defmacro and no backquote at that moment yet, so the actual code looks a lot uglier.

See also Is defun or setf preferred for creating function definitions in common lisp and why? where I discuss macroexpansions of defuns.

Neoplasm answered 26/2, 2017 at 17:24 Comment(0)
P
2

You can easily check how your particular CL implementation, implemented defun by running

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

On SBCL it expands to:

(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

To see the particular source code that implemented the I would use (on Emacs) the M-. key binding and then I will write defun and hit enter. Then Emacs will get to the source code:

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

I am not going to paste the whole macro as it is rather long. If you are not on Emacs, you can try searching in the repos as most implementations are open source.

BTW defun is not so special. You can implement much of it with setf-inf a symbol-function to a lambda. E.g.:

(setf (symbol-function 'ADD3) #'(lambda (x) (+ x 3)))
; => #<FUNCTION (LAMBDA (X)) {1006E94EBB}>
(add3 4)
; => 7
Paramnesia answered 26/2, 2017 at 17:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.