如何在Common Lisp中设置一个函数

时间:2015-09-16 03:17:26

标签: lisp common-lisp

在Common Lisp中,我可以使用#'语法来传递函数,如下所示:

(let ((x #'+))
 (funcall x 1 2))

但是假设我想设置一个函数,所以我不必使用funcall。 Common Lisp是否具有本地函数名称表,或仅具有defun分配给的全局函数名称表?

有没有办法分配给defun以外的功能符号?或者更一般地说:有没有办法可以做一些类似于这个非工作的例子:

(setf #'x #'+)
(x 1 2)

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)))