Это не одно и то же.
Литеральные функции в коде и компиляция файла
Например, посмотрите этот файл example.lisp
:
(defmacro fm ()
(lambda () (print "hi")))
(defun foo ()
(fm))
Теперь скомпилируйте файл с помощью (compile-file "example.lisp")
.
Скорее всего, он не будет работать. SBCL говорит:
; in: DEFUN FOO
; (FM)
; ==>
; #<FUNCTION (LAMBDA () :IN FM) {226680AB}>
;
; caught ERROR:
; Objects of type FUNCTION can't be dumped into fasl files.
;
; compilation unit finished
; caught 1 ERROR condition
Почему это так?
Ваша функция f
возвращает функцию во время выполнения.
Ваш макрос m
возвращает функцию при расширении макроса время. Это означает, что буквенный объект будет включен в код. Литеральные функции обычно не могут быть выгружены файловым компилятором.
Следующий пример: функция и два макроса
(defun f ()
(lambda () (format t "hello world")))
(defmacro m0 ()
(lambda () (format t "hello world")))
(defmacro m1 ()
`(lambda () (format t "hello world")))
(defun foo ()
(list
(f) ; returns a function at runtime
(m0) ; a literal function, created at macro expansion time
; thus can't be dumped by a file compiler
(m1) ; a function form, (function (lambda () ...))
))
Примеры в REPL с переменными
Теперь давайте посмотрим с переменными:
(defun f (a)
(lambda (b) (list a b))) ; A is a lexical reference to above A
(defmacro m0 (a)
(lambda (b) (list a b))) ; A is a lexical reference to above A (!)
(defmacro m1 (a) ; A is unused
`(lambda (b) (list a b))) ; A is not a reference to above A (!)
теперь на REPL:
* (defun foo (c)
(list
(ignore-errors (funcall (f c) 2))
(ignore-errors (funcall (m0 c) 2))
(ignore-errors (funcall (m1 c) 2))
))
; in: DEFUN FOO
; (M1 C)
; --> LAMBDA FUNCTION
; ==>
; (LIST A B)
;
; caught WARNING:
; undefined variable: COMMON-LISP-USER::A
;
; compilation unit finished
; Undefined variable:
; A
; caught 1 WARNING condition
* (foo 3)
((3 2) ; <- runtime values
(C 2) ; <- C is source code
NIL) ; <- error, since A is undefined