LINUX.ORG.RU

Замыкания в lisp


0

1

Вопрос для знатоков лиспа =)
Сейчас читаю SICP. До этого на лиспе никогда не писал. Параллельно смотрю на Common Lisp.
Возникла вот непонятка:
Почему в Common Lisp так странно выглядят замыкания??(по сравнению с Scheme)
И зачем нужен funcall?(см. пример)

Для сравнения:

Scheme:

> (define (tst x)
>   (lambda (y) (+ x y)))
> ((tst 2) 2) ; Все OK.
4

Common Lisp:
* (defun tst (x)
*   (lambda (y) (+ x y)))
* ((tst 2) 2) ; Бида

; in: LAMBDA NIL
;     ((TST 2) 2)
; 
; caught ERROR:
;   illegal function call
; 
; compilation unit finished
;   caught 1 ERROR condition

* (funcall (tst 2) 2) ; Зачем нужен funcall??[br]
4

Аналогично:

Scheme:
> (((lambda (y) (lambda (x) (+ x y))) 5) 5)
10

Common Lisp:
* (((lambda (y) (lambda (x) (+ x y))) 5) 5) ; Почему не прокатило??

; in: LAMBDA NIL
;     (((LAMBDA (Y) (LAMBDA (X) (+ X Y))) 5) 5)
; 
; caught ERROR:
;   illegal function call
; 
; compilation unit finished
;   caught 1 ERROR condition

* (funcall ((lambda (x) (lambda (y) (+ x y))) 5) 5) ; С funcall'ом все работает почему-то...
10

Насколько я понял из вики различия связаны с lisp-1 и lisp-2.

Насколько я понял из вики различия связаны с lisp-1 и lisp-2.

Всё правильно. А в чём вопрос?

ugoday ★★★★★
()

>> И зачем нужен funcall?(см. пример)

Потому, что Scheme и CL - это два разных языка (или диалекта, как больше нравится).

cathode
()

> И зачем нужен funcall?(см. пример)

Затем что в CL как минимум есть отдельное пространство имен для функций, а есть отдельное для переменных. Это дает плюшки в виде возможности называть переменные list, first, second и тд и тп. Чего схемеры лишены. Сделано для того, чтобы легче было писать CL'ные макросы.

anonymous
()
Ответ на: комментарий от kermzyxer

> Что такое funcall и почему в Common Lisp замыкания без него не работают.

работают

(let ((x 1)) (defun test (y) (+ x y)))

(test 1) ;; => 2

anonymous
()
Ответ на: комментарий от kermzyxer

funcall это вызов функции, очевидно. Есть еще apply - примерно то эе самое, только последний аргумент-список раскрывает.

Через них можно вызывать функции, привязанные к переменным.

Но дальше больше - есть еще, например, invoke-restart - через него можно вызывать функции из пространства имен перезапусков. Или signal - из пространства имен обработчиков сигналов.

Doug
()
Ответ на: комментарий от kermzyxer

Всё дело в том, что в КЛ

(defvar p)
(defun p () ...)

является совершенно нормальным кодом. И в далее системе нужно дать понять как интерпретировать символ: как функцию или переменную.

P.S. Рекомендую прочитать что такое символ в КЛ. Тогда всё сразу станет ясно.

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

спс за ответы, почитал про символы и пространства имен, разобрался.

kermzyxer
() автор топика

ТС,

Замыкание - это связка функции и лексического окружения, в котором она была определена. И все.

В CL и Scheme просто отличается механизм применения замыканий. И все.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.