Вызов списка функций в Common Lisp
В Clojure я могу определить последовательность функций, а затем вызвать их, как если бы они были любым другим значением, например:
(doseq [op [+ - * /]]
(println (op 1 2 3 4)))
который производит следующий вывод:
10
-8
24
1/24
nil
Попытка сделать то же самое в Common Lisp приводит только к ошибке:
(dolist (op '(+ - * /))
(print (op 1 2 3 4))
; in: DOLIST (OP '(+ - * /))
; (LET ((OP (TRULY-THE (MEMBER / * - +) (CAR #:N-LIST671))))
; (SETQ #:N-LIST671 (CDR #:N-LIST671))
; (TAGBODY (PRINT (OP 1 2 3 4))))
;
; caught STYLE-WARNING:
; The variable OP is defined but never used.
; in: DOLIST (OP '(+ - * /))
; (OP 1 2 3 4)
;
; caught STYLE-WARNING:
; undefined function: OP
;
; compilation unit finished
; Undefined function:
; OP
; caught 2 STYLE-WARNING conditions
debugger invoked on a UNDEFINED-FUNCTION:
The function COMMON-LISP-USER::OP is undefined.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
("undefined function")
призвание op
как #'op
у меня тоже не сработало.
Так есть ли способ сделать это в CL?
1 ответ
Поскольку пространство имен для функций и пространство имен для данных разделены в LISP-2 (и, следовательно, в common-lisp), вам необходимо использовать funcall
при передаче функций в качестве параметров:
(dolist (op '(+ - * /))
(print (funcall op 1 2 3 4))))
funcall
функция является примерно эквивалентом Clojure apply
и будет применять op
функция по заданным параметрам. В этом случае происходит еще одна вещь, так как op
является символом, связанным с функцией, но funcall
заботится об этом.