我需要创建一个生成如下函数的函数:
(defun add3 (val) (+ 3 val))
应该像这样使用:
(setq adder7 nil) (fset 'adder7 (make-adder 7)) (adder7 3) => 10
理想情况下,函数make-adder应该返回除了参数之外没有任何符号的lambdas,例如:
(make-adder 7) => (lambda (val) (+ 7 val))
更新
我尝试过以下天真的实现:
(defun make-adder (n) (lambda (x) (+ n x)))
但是这会生成一个包含自由符号(不是数字常量!)的lambda,并且它的使用失败.
(defalias 'add1 (make-adder 1)) (add1 2) => Debugger error void-variable n (let ((n 5)) (add1 2)) => 7
这根本不是我想要的.
默认情况下,Emacs依赖于动态范围.这就是n
返回的lambda中的符号引用未绑定变量的原因.要么切换词法作用域,要么使用当前值构建lambda表单n
,如下所示:
(defun make-adder (n) `(lambda (x) (+ ,n x)))
然后:
(defalias 'add1 (make-adder 1)) (add1 3) => 4
我原本以为这个问题是关于Common Lisp(fset应该给我一个提示),你只需要这样做:
(defun make-adder (n) (lambda (x) (+ n x)))
你的函数接受一个n
并返回一个匿名函数,它接受另一个参数x
并产生结果.但是等等,make-adder
只是将一些参数部分应用于函数的特殊情况(有关currying和部分应用之间区别的详细信息,请参阅此问题).部分应用函数的一般方法是:
(defun partial (function &rest partial-args) (lambda (&rest args) (apply function (append partial-args args))))
例如:
(let ((3+ (partial #'+ 3))) (funcall 3+ 7)) => 10