修改功能;保存到lisp中的新功能

时间:2011-06-25 19:34:06

标签: lisp elisp common-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)))))

我的问题具体是如何

  1. 创建foonewfoo的副本 并用值替换正文 上面定义的newbody。 (我有 查看了fsetsetffunction但可能没有使用 他们是正确的。)
  2. 可能将其包装在一个函数中 叫makenewfoo()或其他东西 像这样我可以调用 makenewfoo(foo)并允许此操作 创建newfoo()
  3. 而且,更一般地说,

    1. 通常是这样的 完成或有一个更惯用的 修改功能的方法?
    2. 这是一个非常简单的案例,但是 有一种更普遍的方式 指定列表元素编号 到nth进行修改。对于 例如,实际的功能是 更复杂,有没有办法 递归搜索这个 s表达式树和测试 特定语法并插入此 conditional-transformation 表达之前或之后的表达 (可能使用equal),所以它是 对变化不太敏感 原来的功能?

1 个答案:

答案 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