如何在 Common Lisp 中设置函数
How to set a function in Common Lisp
在 Common Lisp 中,我可以使用 #'
语法获取一个函数来传递,如下所示:
(let ((x #'+))
(funcall x 1 2))
但是假设我想设置一个函数,这样我就不必为它使用 funcall
。 Common Lisp 是否有一个局部函数名称 table,或者只是分配给 defun
的全局函数名称?
有没有办法分配给 defun
以外的函数符号?或者更一般地说:有没有一种方法可以做类似于这个无效示例的事情:
(setf #'x #'+)
(x 1 2)
您可以使用
flet
and labels
:
(flet ((f (x) (1+ (* 2 x))))
(f 7))
==> 15
您还可以使用 fdefinition
:
设置交易品种的函数定义
(setf (fdefinition 'f) #'+)
(f 1 2 3)
==> 6
请注意 let
绑定
value cell of the symbol while flet
bind the function cell。
当符号出现在 "function" 位置时, "function"
使用单元格,而当它出现在 "value" 位置时, "value"
使用的单元格:
(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 is just one implementation of the language ANSI Common Lisp。
获得这种行为的一种选择是编写一个宏来实现它。
(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)))
在 Common Lisp 中,我可以使用 #'
语法获取一个函数来传递,如下所示:
(let ((x #'+))
(funcall x 1 2))
但是假设我想设置一个函数,这样我就不必为它使用 funcall
。 Common Lisp 是否有一个局部函数名称 table,或者只是分配给 defun
的全局函数名称?
有没有办法分配给 defun
以外的函数符号?或者更一般地说:有没有一种方法可以做类似于这个无效示例的事情:
(setf #'x #'+)
(x 1 2)
您可以使用
flet
and labels
:
(flet ((f (x) (1+ (* 2 x))))
(f 7))
==> 15
您还可以使用 fdefinition
:
(setf (fdefinition 'f) #'+)
(f 1 2 3)
==> 6
请注意 let
绑定
value cell of the symbol while flet
bind the function cell。
当符号出现在 "function" 位置时, "function"
使用单元格,而当它出现在 "value" 位置时, "value"
使用的单元格:
(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 is just one implementation of the language ANSI Common Lisp。
获得这种行为的一种选择是编写一个宏来实现它。
(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)))