What is the fundamental difference in the functions defined using defun
and setf
as below and is one method preferred over another outside of style considerations?
Using defun
:
* (defun myfirst (l)
(car l) )
MYFIRST
* (myfirst '(A B C))
A
Using setf
:
* (setf (fdefinition 'myfirst) #'(lambda (l) (car l)))
#<FUNCTION (LAMBDA (L)) {10021B477B}>
* (myfirst '(A B C))
A
If, as according to Wikipedia:
named functions are created by storing a lambda expression in a symbol using the defun macro
Using setf
to create a variable in a different way requires the use of funcall
:
* (defvar myfirst)
MYFIRST
* (setf myfirst (lambda (l) (car l)))
#<Interpreted Function (LAMBDA (X) (+ X X)) {48035001}>
* (funcall myfirst '(A B C))
A
My understanding is that this type of variable is different than the previous in that this variable is not found in the same namespace as the defun bound symbol as described in Why multiple namespaces?.
First of all, one should never underestimate the importance of style. We write code not just for computers to run, but, much more importantly, for people to read. Making code readable and understandable for people is a very important aspect of software development.
Second, yes, there is a big difference between
(setf fdefinition)
anddefun
.The "small" differences are that
defun
can also set the doc string of the function name (actually, depending on how your imeplementation works, it might do that with lambda also), and creates a namedblock
(seen in the macroexpansions below) which you would otherwise have to create yourself if you want to.The big difference is that the compiler "knows" about
defun
and will process it appropriately.E.g., if your file is
then the compiler will probably warn you that you call
foo
inbar
with the wrong number of arguments:If you replace the
defun foo
with(setf (fdefinition 'foo) (lambda ...))
, the compiler is unlikely to handle it as carefully. Moreover, you will probably get a warning along the lines ofYou might want to examine what
defun
does in your implementation by macroexpanding it:CLISP expands it to
SBCL does:
The point here is that
defun
has a lot "under the hood", and for a reason.setf fdefinition
is, on the other hand, more of "what you see is what you get", i.e., no magic involved.This does not mean that
setf fdefinition
has no place in a modern lisp codebase. You can use it, e.g., to implement a "poor man'strace
" (UNTESTED):