在Common Lisp中,我可以使用#'
语法来传递函数,如下所示:
(let ((x #'+))
(funcall x 1 2))
但是假设我想设置一个函数,所以我不必使用funcall
。 Common Lisp是否具有本地函数名称表,或仅具有defun
分配给的全局函数名称表?
有没有办法分配给defun
以外的功能符号?或者更一般地说:有没有办法可以做一些类似于这个非工作的例子:
(setf #'x #'+)
(x 1 2)
答案 0 :(得分:12)
您可以使用定义本地函数
flet
and labels
:
(flet ((f (x) (1+ (* 2 x))))
(f 7))
==> 15
您还可以使用fdefinition
设置符号的功能定义:
(setf (fdefinition 'f) #'+)
(f 1 2 3)
==> 6
请注意let
绑定
flet
绑定value cell时符号的function cell。
当符号出现在“功能”位置时,“功能”
使用单元格,而当它出现在“值”位置时,“值”
使用单元格:
(setf (symbol-function 'x) #'car)
(setf (symbol-value 'x) #'cdr)
(x '(1 . 2))
==> 1
(funcall x '(1 . 2))
==> 2
类似地,
(flet ((x (o) (car o)))
(let ((x #'cdr))
(cons (x '(1 . 2))
(funcall x '(1 . 2)))))
==> (1 . 2)
这是difference between Lisp-1 and Lisp-2。
最后,请注意CLISP只是语言ANSI Common Lisp的一种实现。
答案 1 :(得分:0)
获得此类行为的一个选择是编写宏来执行此操作。
(defmacro flet* (assignments &body body)
(let ((assignments (mapcar
(lambda (assn)
(list (first assn) '(&rest args)
(list 'apply (second assn) 'args)))
assignments)))
`(flet ,assignments ,@body)))
此宏将flet*
翻译为flet
+ apply
,如下所示:
(flet* ((x #'+)
(y #'*))
(pprint (x 1 2))
(pprint (y 3 4))
(pprint (x (y 2 3) 4)))
变为:
(flet ((x (&rest args) (apply #'+ args))
(y (&rest args) (apply #'* args)))
(pprint (x 1 2))
(pprint (y 3 4))
(pprint (x (y 2 3) 4)))