2017-01-14 2 views
2

мне нужно определить функцию внутри позволения и быть в состоянии немедленно использовать его, как это:Как определить функцию локально в lisp?

(let ((test (lambda() (print "ha")))) 
    (test)) 

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

(let ((test (lambda() (print "ha")))) 
    (funcall test)) 

В моем случае это проблема. Я мог бы решить это, сделав макрос, который изменит (тест) на (funcall test), однако это не сработает, поскольку имя макроса будет таким же, как и метод в моем случае (я предполагаю, что это вызовет (тест), чтобы стать (funcall test) => (funcall (funcall test)) => ...?)

Есть ли способ определить метод в лямбда и запустить его немедленно, без чего-то вроде funcall?

+0

функции называются * функциями *, а не * методами *. Нет * локальных методов *. –

ответ

9

См. Special Operator FLET, LABELS, MACROLET . Обратите внимание на разницу между FLET и LABELS. В частности, LABELS можно определить (взаимно) рекурсивные функции, тогда как FLET может тень существующей функции, будучи в состоянии назвать саму эту функцию:

(defun foo() (flet ((foo() (foo))) (foo))) 
     ^1    ^2  ^1  ^2 

(defun foo() (labels ((foo() (foo))) (foo))) 
     ^1    ^2  ^2  ^2 
3

Вы можете использовать labels для этого, так же, как и для переменных. let. т.е.:

(labels ((test() 
      (print "ha"))) 
    (test)) 
6

я мог бы решить эту проблему, сделав макрос, который изменяет (тест) до (funcall test), однако это не сработало

Почему бы и нет?

CL-USER 4 > (let ((test (lambda() (print "ha")))) 
       (macrolet ((test() 
          `(funcall test))) 
       (test))) 

"ha" 
"ha" 
Смежные вопросы