修改功能;保存到Lisp中的新功能 [英] Modifying function; saving to new function in lisp
问题描述
因此,我认为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表达式树并测试a 特定语法并插入此conditional-transformation
之前或之后的表达 (可能使用equal
),因此 对所做的更改不太敏感 原始功能?
它在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
和:around
方法. /p>
用于插入表达式的示例代码:
(defun find-node (elt tree)
(cond ((null tree) nil)
((equal (car tree) elt) tree)
((consp (car tree)) (let ((node (find-node elt (car tree))))
(if node node (find-node elt (cdr tree)))))
(t (find-node elt (cdr tree)))))
(defun insert-before (node elt)
(setcdr node (cons (car node) (cdr node)))
(setcar node elt))
(let* ((function (copy-tree (symbol-function 'foo)))
(node (find-node '(+ x y) function)))
(when node
(insert-before node '(if (< x 2) (setq x (* x 2))))
(fset 'newfoo function)))
So I thought one of the advantages of lisp (among other languages) is its ability to implement function factories (accept functions as arguments; return new functions). I want to use this capability to make small changes to a function and save it as a new function so that if changes are made to the original function, they are also reflected in the new function on which it is based. Note: I am not the one writing the original function so I can't necessarily encapsulate the common parts in a separate function to be called by both, which would be the obvious answer otherwise.
Toy example in emacs lisp (may not be the most ideal as it is a lisp-2):
I have a function, foo
that is provided to me:
(defun foo (x y)
(+ x y)))
I want my new function to include a statement that allows me to change the value of a variable if a certain condition is met. For instance:
(defun newfoo (x y)
(if (condition-met-p x)
(setq x (transform x)))
(+ x y))
Please disregard that I could use defadvice
in this particular example as I am more interested in the general task of modifying functions where defadvice
may not apply. I believe I can modify the body with this form:
(setq conditional-transformation
'(if (condition-met x) (setq x (transform x))))
(setq newbody (append conditional-transformation
(nth 2 (symbol-function 'foo)))))
My questions are specifically how to
- create a copy of
foo
tonewfoo
and replace the body with the value ofnewbody
defined above. (I've looked intofset
,setf
, andfunction
but perhaps not using them properly.) - possibly wrap this in a function
called
makenewfoo()
or something like this so I can invokemakenewfoo(foo)
and allow this to createnewfoo()
.
And, more generally,
- is something like this is commonly done or there is a more idiomatic way to modify functions?
- this is a very simple case, but is
there a more general way than
specifying the list element number
to
nth
for the modification. For instance, the actual function is more complex so is there a way to recursively search down this s-expression tree and test for a particular syntax and insert thisconditional-transformation
expression before or after it (possibly usingequal
), so it is less sensitive to changes made in the original function?
It does work in 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
But I really don't think that it is commonly done or idiomatic. You should use defadvice
if you want to modify the behavior of functions.
As far as CL is concerned: Some implementations provide similar functions/macros (for example in CCL: ccl:advise
), and you can specify :before
, :after
, and :around
methods for generic functions.
Example code for insertion of expressions:
(defun find-node (elt tree)
(cond ((null tree) nil)
((equal (car tree) elt) tree)
((consp (car tree)) (let ((node (find-node elt (car tree))))
(if node node (find-node elt (cdr tree)))))
(t (find-node elt (cdr tree)))))
(defun insert-before (node elt)
(setcdr node (cons (car node) (cdr node)))
(setcar node elt))
(let* ((function (copy-tree (symbol-function 'foo)))
(node (find-node '(+ x y) function)))
(when node
(insert-before node '(if (< x 2) (setq x (* x 2))))
(fset 'newfoo function)))
这篇关于修改功能;保存到Lisp中的新功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!