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:
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: