возвращая лямбда-функцию в clisp, затем оценивая ее - PullRequest
5 голосов
/ 03 декабря 2009

Предположим, у меня есть эта замечательная функция foo

[92]> (defun foo () (lambda() 42))
FOO
[93]> (foo)
#<FUNCTION :LAMBDA NIL 42>
[94]> 

Теперь предположим, что я действительно хочу использовать foo и вернуть 42.

Как мне это сделать? Я копался в Google и не могу найти правильный синтаксис.

Ответы [ 4 ]

11 голосов
/ 03 декабря 2009

Требуется функция FUNCALL:

* (defun foo () (lambda () 42))
FOO
* (funcall (foo))
42
6 голосов
/ 07 декабря 2009

Здесь применимы следующие термины: " Lisp-1 " и " Lisp-2 ".

Ваша попытка вызова будет работать в Лисп-1, например, например. Схема или Clojure. Common Lisp - это Lisp-2, который примерно означает, что имена переменных и имена функций разделены.

Таким образом, для вызова функции, связанной с переменной, вам нужно либо использовать специальные формы funcall или apply, как указали другие, либо установить значение функции символа foo вместо переменной значение.

Первый в основном принимает значение переменной символа, предполагает / проверяет, что значение является функцией, а затем вызывает функцию (с любыми аргументами, которые вы передали funcall / apply.

Вы действительно не хотите делать последнее, поскольку это довольно глупо во всех случаях, кроме очень специализированных, но для полноты картины это примерно так:

CL-USER> (setf (symbol-function 'foo) (lambda () 42))
#<FUNCTION (LAMBDA ()) {C43DCFD}>
CL-USER> (foo)
42

Вам также следует изучить специальные формы labels и flet (которые обычно используются) - там вы на самом деле do используете последние методы (эти формы создают временную привязку функции для символы).

Итак, ваша проблема будет выглядеть так:

(flet ((foo () 
         42))
  (foo))

т.е. здесь вы временно привязываете значение function символа foo к функции, возвращающей 42. В этом временном контексте вы можете затем вызывать (foo) как обычные глобальные функции.

2 голосов
/ 04 декабря 2009

Другой вариант, кроме FUNCALL, это ПРИМЕНИТЬ:

(apply (foo) nil)

FUNCALL - идиоматический способ, но вам потребуется APPLY, когда у вас есть список параметров.

2 голосов
/ 03 декабря 2009

Ваша функция foo возвращает функцию . Используйте функцию funcall, чтобы применить функцию к аргументам, даже если набор аргументов пуст.

Здесь вы можете видеть, что foo возвращает значение типа function:

CL-USER> (let ((f (foo)))
           (type-of f))
FUNCTION
CL-USER> (let ((f (foo)))
           (funcall f))
42
CL-USER> (type-of (foo))
FUNCTION
CL-USER> (funcall (foo))
42
...