我想用一个参数来定义一个函数,该参数定义了另一个以该参数作为名称的函数。
不工作的例子:
(DEFUN custom (name op const var)
(DEFUN name (var) (op const var)))
问题是名称未经评估,因此定义的函数始终称为名称。
我知道FUNCALL
和APPLY
可以动态评估参数,但我不知道如何正确调用FUNCALL
DEFUN...
。
答案 0 :(得分:4)
我认为你不能使用嵌套的defuns。
(defun custom (op const)
(lambda (arg) (funcall op const arg)))
然后使用fdefinition
:
(setf (fdefinition '+42) (custom '+ '42))
或使用defmacro
:
(defmacro custom (name op const)
(let ((arg (gensym)))
`(defun ,name (,arg)
(,op ,const ,arg))))
(custom +42 + 42)
PS。我认为您需要解释为什么要这样做,然后我们将能够更好地解释您的选择。
答案 1 :(得分:1)
在我看来,你可能想要一个功能。想象一下,你这样做了:
(defun curry (op arg1)
(lambda (&rest args) (apply op (cons arg1 args))))
(funcall (curry #'+ 10) 20) ; ==> 30
(mapcar (curry #'+ 10) '(1 2 3 4)) ; ==> (11 12 13 14)
现在defun
始终在全局命名空间中生成一个函数。它不像在Scheme中创建一个闭包。要与defun
执行相同操作,我们使用symbol-function
和setf
:
(defun create-curried (name op arg1)
(setf (symbol-function name)
(lambda (&rest args) (apply op (cons arg1 args)))))
(create-curried '+x #'+ 10) ; ==> function
(+x 20) ; ==> 30
;; since it's a function, it even works with higher order functions
(mapcar create-curried '(+x -x /x *x) (list #'+ #'- #'/ #'*) '(10 10 10 10))
(/x 2) ; ==> 5
最后。使用宏,你可以美化它。
(defmacro defun-curried (newname oldname arg)
(if (and (symbolp newname) (symbolp oldname))
`(create-curried ',newname (function ,oldname) ,arg)
(error "Newname and Oldname need to be symbols")))
(defun-curried +xx + 20)
(+xx 10) ; ==> 30
oldname
取自词汇范围,因此您可以使用flet
或labels
,但它最终是全局的,就像使用defun
一样。
答案 2 :(得分:1)
主要问题是DEFUN
不是函数,它是一个专门处理其参数的宏(具体来说,它没有评估"函数名称" ;,"参数列表",而不是"函数体")。
你可以通过谨慎使用(setf (symbol-function ...) ...)
来制作一些东西,比如:
(defun define-custom-function (name op const)
(setf (symbol-function name) (lambda (var) (funcall op const var))))
这会将符号的函数定义绑定到一个匿名函数,该函数调用您的"运算符"在你的输入常数。
* (defun define-custom-function (name op const)
(setf (symbol-function name) (lambda (var) (funcall op const var))))
DEFINE-CUSTOM-FUNCTION
* (define-custom-function 'add3 #'+ 3)
#<CLOSURE (LAMBDA (VAR) :IN DEFINE-CUSTOM-FUNCTION) {1002A4760B}>
* (add3 5)
8
但是,除非您绝对需要动态定义(或重新定义)这些自定义函数,否则最好定义一个自定义DEFUN
- 就像宏一样。