Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is the defun macro implemented in lisp?

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.

like image 951
Denis Nutiu Avatar asked Feb 26 '17 16:02

Denis Nutiu


2 Answers

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.

like image 170
sds Avatar answered Dec 11 '22 08:12

sds


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
like image 39
tsikov Avatar answered Dec 11 '22 07:12

tsikov