所以我认为lisp(以及其他语言)的一个优点是它能够实现函数工厂(接受函数作为参数;返回新函数)。我想使用此功能对函数进行小的更改并将其保存为新函数,以便在对原始函数进行更改时,它们也会反映在它所基于的新函数中。注意:我不是那个编写原始函数的人,所以我不一定将公共部分封装在一个单独的函数中,以便两者调用,否则这将是明显的答案。
emacs lisp中的玩具示例(可能不是最理想的,因为它是lisp-2):
我有一个提供给我的函数foo
:
(defun foo (x y)
(+ x y)))
我希望我的新函数包含一个语句,允许我在满足某个条件时更改变量的值。例如:
(defun newfoo (x y)
(if (condition-met-p x)
(setq x (transform x)))
(+ x y))
请忽略我可以在此特定示例中使用defadvice
,因为我对修改defadvice
可能不适用的函数的一般任务更感兴趣。我相信我可以用这种形式修改身体:
(setq conditional-transformation
'(if (condition-met x) (setq x (transform x))))
(setq newbody (append conditional-transformation
(nth 2 (symbol-function 'foo)))))
我的问题具体是如何
foo
到newfoo
的副本
并用值替换正文
上面定义的newbody
。 (我有
查看了fset
,setf
和
function
但可能没有使用
他们是正确的。)makenewfoo()
或其他东西
像这样我可以调用
makenewfoo(foo)
并允许此操作
创建newfoo()
。而且,更一般地说,
nth
进行修改。对于
例如,实际的功能是
更复杂,有没有办法
递归搜索这个
s表达式树和测试
特定语法并插入此
conditional-transformation
表达之前或之后的表达
(可能使用equal
),所以它是
对变化不太敏感
原来的功能?答案 0 :(得分:3)
它在Emacs Lisp中有效:
elisp> (defun foo (x y)
(+ x y))
foo
elisp> (fset 'newfoo
(append (lambda (x y)
(when (< x 2)
(setq x (* x 2))))
(cddr (symbol-function 'foo))))
(lambda
(x y)
(when
(< x 2)
(setq x
(* x 2)))
(+ x y))
elisp> (newfoo 1 3)
5
elisp> (newfoo 3 3)
6
但我真的不认为这是常见的或惯用的。如果要修改函数的行为,则应使用defadvice
。
就CL而言:某些实现提供了类似的功能/宏(例如在CCL中:ccl:advise
),您可以指定:before
,:after
和{{1通用函数的方法。
插入表达式的示例代码:
:around