Возврат лямбды с функцией против макро с общим lisp - PullRequest
0 голосов
/ 17 февраля 2020

В чем разница между использованием макроса и функции для возврата лямбда в общем lisp?

(defun f ()
  (lambda () (format t "hello world")))

(defmacro m ()
  (lambda () (format t "hello world")))

; is (f) equal to (m) ?

они возвращают одну и ту же вещь?

А что, если возвращенные лямбда-формы были процитированы? ('(lambda ...))

Я спрашиваю об этом, потому что в главе 3 Практического общего Лисп есть макрос (where), который возвращает (обратно) лямбда в кавычках, и я не понимаю, почему не может быть простой функцией, которая возвращает ту же лямбду.

1 Ответ

3 голосов
/ 17 февраля 2020

Это не одно и то же.

Литеральные функции в коде и компиляция файла

Например, посмотрите этот файл 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...