How to use only one move function for all shapes - lisp
I have a problem with move function in my code.
I need it to be :
one function which can move all shapes or,
multiple functions with the same name.
So far I have move functions with diffrent names for point, circle and polygon.
I can't figure out how to make move function for picture.
If you guys can help me with that move function for picture and edit all the move function so they work like I described at beginning.
;
; POINT
;
(defun make-point ()
(list (list 0 0) :black))
(defun x (point)
(caar point))
(defun y (point)
(cadar point))
(defun set-x (point new-x)
(setf (caar point) new-x)
point)
(defun set-y (point new-y)
(setf (cadar point) new-y)
point)
(defun move (point dx dy)
(set-x point (+ (x point) dx))
(set-y point (+ (y point) dy))
point)
;
; CIRCLE
;
(defun make-circle ()
(list (make-point) 1 :black))
(defun center (circle)
(car circle))
(defun radius (circle)
(cadr circle))
(defun set-radius (circle new-rad)
(if (> 0 new-rad)
(format t "Polomer ma byt kladne cislo, zadali ste : ~s" new-rad)
(setf (cadr circle) new-rad))
circle)
(defun movec (circle dx dy)
(move (center circle) dx dy)
circle)
;
; POLYGON
;
(defun make-polygon ()
(list nil :black))
(defun items (shape)
(car shape))
(defun set-items (shape val)
(setf (car shape) val)
shape)
(defun movep (polygon dx dy)
(mapcar (lambda (b) (move b dx dy)) (items polygon))
polygon)
;
; PICTURE
;
(defun make-picture ()
(list nil :black))
;(defun movepi (picture dx dy))
; items, set-items used for polygon and picture
Your objects are just lists, you will have a hard time distinguishing among different kinds of shapes. You could add a keyword, a tag type, in front of your lists (e.g. :point, :circle, etc.) to better dispatch your move operations according to that tag, but then that would be reinventing the wheel, a.k.a. objects.
Simple functions and lists
one function which can move all shapes
You can do that, provided you can dispatch on the actual type of object you are working with. move should be able to know what kind of shape is being moved. Change your data-structures if you can to add the type of object as the CAR of your lists, and use a CASE to dispatch and then move each object as needed.
or multiple functions with the same name.
This is not possible, at least in the same package.
CLOS
(defpackage :pic (:use :cl))
(in-package :pic)
Multiple shapes have a color, so let's define a class that represent objects which have a color component:
(defclass has-color ()
((color :initarg :color :accessor color)))
If you are unfamiliar with CLOS (Common Lisp Object System), the above defines a class named has-color, with no superclass and a single slot, color. The accessor names both the reader and writer generic functions, such that you can do (color object) to retrieve an object, and (setf (color object) color) to set the color of an object to a color. The :initarg is used to define the keyword argument that is to be used in make-instance.
Here below, we define a point, which has a color and additional x and y coordinates.
(defclass point (has-color)
((x :initarg :x :accessor x)
(y :initarg :y :accessor y)))
The same for a circle:
(defclass circle (has-color)
((center :initarg :center :accessor center)
(radius :initarg :radius :accessor radius)))
And a polygon:
(defclass polygon (has-color)
((points :initarg :points :accessor points)))
Finally, a picture is a sequence of shapes:
(defclass picture ()
((shapes :initarg :shapes :accessor shapes)))
You can make a circle as follows:
(make-instance 'circle
:center (make-instance 'point :x 10 :y 30)
:color :black))
You could also define shorter constructor functions, if you wanted.
Now, you can use a generic function to move your objects. You first define it with DEFGENERIC, which declares the signature of the generic function, as well as additional options.
(defgeneric move (object dx dy)
(:documentation "Move OBJECT by DX and DY"))
Now, you can add methods to that generic function, and your generic function will dispatch to them based on one or more specializers and/or qualifiers.
For example, you move a point as follows:
(defmethod move ((point point) dx dy)
(incf (x point) dx)
(incf (y point) dy))
You can see that we specialize move based on the class of the first parameter, here named point. The method is applied when the value bound to point is of class point. The call to INCF implicitly calls (setf x) and (setf y), defined above.
Moving a circle means moving its center:
(defmethod move ((circle circle) dx dy)
(move (center circle) dx dy))
You can specialize a generic function on any class, for example the standard SEQUENCE class. It moves all the objects in the sequence with the same offsets:
(defmethod move ((sequence sequence) dx dy)
(map () (lambda (object) (move object dx dy)) sequence))
This is useful for polygons:
(defmethod move ((polygon polygon) dx dy)
(move (points polygon) dx dy))
And also for pictures:
(defmethod move ((picture picture) dx dy)
(move (shapes picture) dx dy))
Immutable version
You could also make move build new instances, but that requires to somehow make copies of existing objects. A simple approach consists in having a generic function which fills a target instance with a source instance:
(defgeneric fill-copy (source target)
(:method-combination progn))
The method combination here means that all methods that satisfy fill-copy are run, instead of only the most specific one. The progn suggests that all methods are run in a progn block, one after the other. With the above definition, we can define a simple copy-object generic function:
(defgeneric copy-object (source)
(:method (source)
(let ((copy (allocate-instance (class-of source))))
(fill-copy source copy)
copy)))
The above defines a generic function named copy-object, as well as a default method for an object of type T (any object).
ALLOCATE-INSTANCE creates an instance but does not initialize it. The method uses FILL-COPY to copy slot values.
You can for example define how to copy the color slot of any object that has a color:
(defmethod fill-copy progn ((source has-color) (target has-color))
(setf (color target) (color source)))
Notice that you have multiple dispatch here: both the source and target objects must be of class has-color for the method to be called. The progn method combination allows to distribute the job of fill-copy among different, decoupled, methods:
(defmethod fill-copy progn ((source point) (target point))
(setf (x target) (x source))
(setf (y target) (y source)))
If you give a point to fill-copy, two methods can be applied, based on the class hierarchy of point: the one defined for has-color, and the one specialized on the point class (for both arguments). The progn method combination ensures both are executed.
Since some slots can be unbound, it is possible that fill-copy fails. We can remedy to that by adding an error handler around fill-copy:
(defmethod fill-copy :around (source target)
(ignore-errors (call-next-method)))
The (call-next-method) form calls the other methods (those defined by the progn qualifier), but we wrap it inside ignore-errors.
Here no color is defined, but the copy succeeds:
(copy-object (make-point :x 30 :y 20))
=> #<POINT {1008480D93}>
We can now keep our existing, mutating, move methods, and wrap them in a :around specialized method that first make a copy:
(defmethod move :around (object dx dy)
;; copy and mutate
(let ((copy (copy-object object)))
(prog1 copy
(call-next-method copy dx dy))))
In order to see what happens, define a method for PRINT-OBJECT:
(defmethod print-object ((point point) stream)
(print-unreadable-object (point stream :identity t :type t)
(format stream "x:~a y:~a" (x point) (y point))))
And now, moving a point creates a new point:
(let ((point (make-instance 'point :x 10 :y 20)))
(list point (move point 10 20)))
=> (#<POINT x:10 y:20 {1003F7A4F3}> #<POINT x:20 y:40 {1003F7A573}>)
You would still need to change the method for the SEQUENCE type, which currently discards the return values of move, but apart from that there is little change to make to existing code.
Note also that the above approach is mostly used as a way to describe the various uses of CLOS, and in practice you would probably choose one way or another to move points (mutable or not), or you would have different functions instead of a single generic one (e.g. mut-move and move).
Rough sketch, tag shapes:
(defun p (x y) (list x y))
(defun make-shape (type points colour data)
(list* type points colour data))
(defmacro defshape (name args &key verify-points verify-args)
"define the function (make-NAME points ARGS...)
to make a shape of type :NAME. Optionally
evaluate the form VERIFY-ARGS with the
lambda-list ARGS bound and call the
function VERIFY-POINTS with the points of
the shape, ignoring its result."
(let ((type (intern name (symbol-package :key)))
(fun (intern (concatenate 'String "MAKE-" name) (symbol-package name)))
(all (gensym "ARGS"))
(colour (gensym "COLOUR"))
(points (gensym "POINTS")))
`(defun ,fun (,points ,colour &rest ,all)
(destructuring-bind ,args ,all
,verify-args
,(if verify-points `(funcall ,verify-points ,points))
(make-shape ,type ,points ,colour ,all))))
(defun singlep (list) (and list (null (cdr list))))
(defshape point () :verify-points #'singlep
(defshape circle (radius) :verify-args (assert (realp radius) radius)
:verify-points #'singlep)
(defshape polygon ())
You can use this:
CL-USER> (make-circle (list (p 0 0)) :black 2)
(:CIRCLE ((0 0)) :BLACK)
CL-USER> (make-point (list (p 1 2)) :blue)
(:POINT ((1 2)) :BLUE)
CL-USER> (make-polygon (list (p 0 0) (p 0 1) (p 1 0)) :red)
(:POLYGON ((0 0) (0 1) (1 0)) :RED)
And you can write some functions:
(defun map-points (function shape)
(destructuring-bind (type points colour &rest data)
shape
(make-shape type (mapcar function points) colour data)))
And apply them:
CL-USER> (map-points (lambda (p) (list (1+ (first p)) (second p))) '(:POLYGON ((0 0) (0 1) (1 0)) :RED))
(:POLYGON ((1 0) (1 1) (2 0)) :RED)
And solve your problem:
(defun move (dx dy shape)
(map-points (lambda (p) (destructuring-bind (x y) p (list (+ x dx) (+ y dy)))) shape))
Another thing you might want is a big case based on the type (ie CAR) of the shape, of you dispatch based on mapping the type to something in a hash table, or putting something in its symbol plist.
Related
What is a didatic example of the with-slots macro in CLOS?
The Common Lisp HyperSpec covers the with-slots macro. However, the example is hard to grasp. Is there an easier and more didactic example about it?
To better understand with-slots, one should look into defclass first. No reader or writer functions are defined by default; their generation must be explicitly requested. However, slots can always be accessed using slot-value. It means that, unless specific request, defclass don't create any accessor for the slots: > (defclass point () (x y)) (let ((new-point (make-instance 'point))) (setf (point-x new-point) 1)) Error: The function (COMMON-LISP:SETF COMMON-LISP-USER::POINT-X) is undefined. In this case, one must use the slot-value function to access or modify the slot value. (defclass point () (x y)) (let ((new-point (make-instance 'point))) (setf (slot-value new-point 'x) 1)) Obviously, when there are several slots to update, the code become a little cumbersome: (defmethod translate ((point-instance point) delta-x delta-y) (setf (slot-value point-instance 'x) (+ (slot-value point-instance 'x) delta-x)) (setf (slot-value point-instance 'y) (+ (slot-value point-instance 'y) delta-y))) For that reason, the with-slots macro can make the code easier to read: (defmethod translate ((point-instance point) delta-x delta-y) (with-slots (x y) point-instance (setf x (+ x delta-x)) (setf y (+ y delta-y))))
Yes. This (great) tutorial of 2003 has a good one from the geometry domain. Create a class to represent points in 3-dimensions: (defclass point () (x y z)) Create a variable to instantiate the class and a function to set the values: (defvar my-point (make-instance 'point)) (defun set-point-values (point x y z) (setf (slot-value point 'x) x (slot-value point 'y) y (slot-value point 'z) z)) In the REPL, do: CL-USER 17 > (set-point-values my-point 3 4 12) 12 Now, think about a function to compute the distance between points. A brute force way would be: (defun brute-force-distance-from-origin (point) (let ((x (slot-value point 'x)) (y (slot-value point 'y)) (z (slot-value point 'z))) (sqrt (+ (* x x) (* y y) (* z z))))) Using the with-slots macro: (defun distance-from-origin (point) (with-slots (x y z) point (sqrt (+ (* x x) (* y y) (* z z))))) Calling the function in the REPL works as expected: CL-USER> (distance-from-origin my-point) 13.0
Does racket allow for function overloading?
I am new to Lisp-scheme and fairly new to the functional paradigm as a whole, and am currently doing an assignment which requires me to overload a function with the same name, but different sets of parameters in racket. Below is an example of what I'm trying to achieve: #lang racket (define (put-ball-in-box two-by-fours nails ball) ... ) (define (put-ball-in-box box ball) ... ) These are not the actual functions, but close enough. As implied, both functions would put a ball in a box, but one would assemble the box from its components first, then call the other. Obviously, when I try the above in DrRacket or using the command line, I get a module: duplicate definition for identifier ... error. Is there a way to achieve this in racket? Maybe the answer is right in front of me, but I have spent the last two hours searching for this and couldn't find anything, so would appreciate any pointers. Thank you.
It doesn't in the usual sense of "writing another definition somewhere else." It allows shadowing, which is defining a procedure with the same name as an imported procedure. Thus you can (define + ...) and your definition of + will hide the + from racket/base. If you want the original procedure, then you can do something like the following, where I define + to be either addition or string-appending. #lang racket/base (require (rename-in racket/base (+ base:+))) (define (+ . args) (if (andmap string? args) (apply string-append args) (apply base:+ args))) Another thing you can do is use racket/match to have different behavior based on the shape of the argument. #lang racket/base (require racket/match) (define (fib . arg) (match arg [(list n) (fib n 1 0)] [(list 1 a b) a] [(list 0 a b) b] [(list n a b) (fib (sub1 n) (+ a b) a)])) This second example still doesn't quite do what you want since you have to go to the original definition point and modify the match clauses. But it might be sufficient for your purposes. A more complicated example would be to use custom syntax to create a define/overload form. But I think you'll find the racket/match solution to be best.
You have the concept of default values as in JS and PHP: (define (fib n (a 0) (b 1)) (if (zero? n) a (fib (sub1 n) b (+ a b)))) (fib 10) ; ==> 55 Now if you had 5 optional parameters you need to order them and even pass some values just to be able to add a later one. To avoid that you can use keywords: (define (test name #:nick [nick name] #:job [job "vacant"]) (list name nick job)) (test "sylwester" #:job "programmer") ; ==> ("sylwester" "sylwester" "programmer") Now Racket has classes. You can call a method like (send object method args ...). (define circle% (class object% (super-new) (init-field radius) (define/public (area) (* radius radius 3.1415)))) (define cube% (class object% (super-new) (init-field side) (define/public (area) (* side side)))) (define circle (new circle% [radius 7])) (define cube (new cube% [side 7])) (map (lambda (o) (send o area)) (list circle cube)) ; ==> (153.9335 49) Notice that the two classes hasn't really commited to a joint interface with area so this is pure duck typing. Thus you can make a function that expects a class that implements a message and it doesn't need to worry about other aspects of the class at all.
Creating a function to return a core expression using macros
I've been working on some code using R5RS for an assignment to expand certain expressions into core forms of the expression using macros. These are put through a provided eval/apply loop later (define expand (lambda (exp) (letrec-syntax ((let (syntax-rules () ((_ ((var init) ...) body ...) (`((lambda (var ...) body ...) init ...))))) ) (exp)) ; sequence to expand )) (expand (let ((x 2) (y 1)) (+ x y)) ) When I run the code like this I get back ;The object 3 is not applicable. but so it looks like it's actually evaluating exp, but I need to get back a uh...string representation. If I embed the expression I want expanded into the letrec-syntax body I get back what I actually want. Like so: (define expand (lambda (exp) (letrec-syntax ((let (syntax-rules () ((_ ((var init) ...) body ...) (`((lambda (var ...) body ...) init ...))))) ) (let ((x 2) (y 1)) (+ x y))) ; sequence to expand )) I get back ... ;The object ((lambda (x y) (+ x y)) 2 1) is not applicable Which looks like what I want to send back to be interpreted. So my question is how can I rewrite this to take any exp given to expand like in the first example, but return its expanded form like in the second example? I think the problem has something to do with exp defined by lambda being in the wrong scope in regards to letrec-syntax. I'm very new to Scheme, and I feel like I'm missing a simple solution here. My best leads so far involve using syntax-case somehow or something about hygienics, but I feel like I've been chasing my tail trying to research those topics so far and I'm not sure they're the right direction. Thanks for any assistance. :)
This works: (define-syntax expand (syntax-rules (let) ((_ (let ((var init) ...) body ...)) '((lambda (var ...) body ...) init ...)))) then > (expand (let ((x 2) (y 1)) (+ x y))) ((lambda (x y) (+ x y)) 2 1)
Conditional variable binding in Common Lisp
I want to execute a function with 2 local variables, but the values of these of these variables should depend on some condition. For example, let's say I have 2 variables x and y, and I want to swap them inside let if y > x. The swap should be temporary, I don't want to mutate state with rotatef. My code would look something like: (setq x 2) (setq y 1) (let (if (> x y) ((x y) (y x)) ((x x) (y y))) (cons x y)) ; should return (1 . 2) But the expression inside let is not valid Lisp. How do I conditionally assign values to local variables? The work around is to put the body in flet and call it with different arguments, but it look clumsy: (flet ((body (x y) (cons x y))) (if (< x y) (body x y) (body y x)))
Multiple-value-bind and values There are lots of alternatives, some of which have already been pointed out in other answers. I think that the question in the title ("Conditional variable binding in Common Lisp") is a nice case for multiple-value-bind and values. I've used different variable names in the following just to make it clear where x and y are, and where the original values are coming from. The names can be the same, though; this just shadows them inside. (let ((a 3) (b 2)) (multiple-value-bind (x y) (if (< a b) (values a b) (values b a)) (cons x y))) ;=> (2 . 3) Then, using a bit of macrology, we can make this a bit cleaner, much like coredump did: (defmacro if-let (test bindings &body body) "* Syntax: let ({var | (var [then-form [else-form]])}*) declaration* form* => result* * Description: Similar to LET, but each binding instead of an init-form can have a then-form and and else-form. Both are optional, and default to NIL. The test is evaluated, then variables are bound to the results of the then-forms or the else-forms, as by LET." (let ((bindings (mapcar #'(lambda (binding) (destructuring-bind (variable &optional then else) (if (listp binding) binding (list binding)) (list variable then else))) bindings))) `(multiple-value-bind ,(mapcar 'first bindings) (if ,test (values ,#(mapcar 'second bindings)) (values ,#(mapcar 'third bindings))) ,#body))) (pprint (macroexpand-1 '(if-let (< x y) ((x x y) (y y x)) (cons x y)))) ; (MULTIPLE-VALUE-BIND (X Y) ; (IF (< X Y) ; (VALUES X Y) ; (VALUES Y X)) ; (CONS X Y)) (let ((a 3) (b 2)) (if-let (< a b) ((x a b) (y b a)) (cons x y))) ;=> (2 . 3) Comparison with progv In terms of use, this has some similarities with sindikat's answer, but multiple-value-bind establishes bindings just like let does: lexical by default, but a global or local special declaration will make the bindings dynamic. On the other hand, progv establishes dynamic bindings. This means that if the bindings are entirely introduced by progv, you won't see much difference (except in trying to return closures), but that you can't shadow bindings. We can see this without having to do any conditional work at all. Here are two sample snippets. In the first, we see that the inner reference to x actually refers to the lexical binding, not the dynamic one established by progv. To refer to the one established by progv, you actually need to declare the inner reference to be special. progv doesn't accept declarations, but we can use locally. (let ((x 1)) (progv '(x) '(2) x)) ;=> 1 (let ((x 1)) (progv '(x) '(2) (locally (declare (special x)) x))) ;=> 2 multiple-value-bind actually does the binding the way we'd expect: (let ((x 1)) (multiple-value-bind (x) (values 2) x)) ;=> 2 It's probably better to use a binding construct like multiple-value-bind that establishes lexical bindings by default, just like let does.
If you don't want to use progv, as mentioned by sindikat, you always can wtite something like that: (defmacro let-if (if-condition then-bindings else-bindings &body body) `(if ,if-condition (let ,then-bindings ,#body) (let ,else-bindings ,#body))) So expression like (let-if (> x y) ((x y) (y x)) ((x x) (y y)) (cons x y)) Will expand into: (IF (> X Y) (LET ((X Y) (Y X)) (CONS X Y)) (LET ((X X) (Y Y)) (CONS X Y)))
rotatef How about: CL-USER> (defvar x 2) X CL-USER> (defvar y 1) Y CL-USER> (let ((x x) ; these variables shadow previously defined (y y)) ; X and Y in body of LET (when (> x y) (rotatef x y)) (cons x y)) (1 . 2) CL-USER> x ; here the original variables are intact 2 ; ^ CL-USER> y ; ^ 1 ; ^ However, I think that in every such practical case there are lispier ways to solve problem without macros. Answer by msandiford is probably the best from functional point of view. psetf Although rotatef is really efficient method (it probably would be compiled to about three machine instructions swapping pointers in memory), it is not general. Rainer Joswing posted just a great solution as a comment shortly after posting of the question. To my shame, I checked macro psetf only few minutes ago, and this should be very efficient and general solution. Macro psetf first evaluates its even arguments, then assigns evaluated values to variables at odd positions just like setf does. So we can write: (let ((x x) (y y)) (when (> x y) (psetf x y y x)) ...) And that's it, one can conditionally rebind anything to anything. I think it's way better than using macros. Because: I don't think it's such a common situation; Some macros in the posted answers repeat their body code, which may be really big: thus you get bigger compiled file (it's fair price for using macro, but not in this case); Every custom macro does make code harder to understand for other people.
One solution is to use progv instead of let, its first argument is a list of symbols to bind values to, second argument is a list of values, rest is body. (progv '(x y) (if (< x y) (list x y) (list y x)) (cons x y)) ; outputs (1 . 2)
Another alternative might be: (let ((x (min x y)) (y (max x y))) (cons x y))
My suggestion would be one of destructuring-bind or multiple-value-bind. If you anticipate needing to do this a lot, I would suggest using a macro to generate the bindings. I've provided a possible macro (untested). (defmacro cond-let (test-expr var-bindings &body body) "Execute BODY with the VAR-BINDINGS in place, with the bound values depending on the trueness of TEST-EXPR. VAR-BINDINGS is a list of (<var> <true-value> <false-value>) with missing values being replaced by NIL." (let ((var-list (mapcar #'car var-bindings)) (then-values (mapcar #'(lambda (l) (when (cdr l) (nth 1 l))) var-bindings)) (else-values (mapcar #'(lambda (l) (when (cddr l)) (nth 2 l))) var-bindings)) `(destructuring-bind ,var-list (if ,test-expr (list ,#then-values) (list ,#else-values)))))
Modifying function; saving to new function in lisp
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 to newfoo and replace the body with the value of newbody defined above. (I've looked into fset, setf, and function but perhaps not using them properly.) possibly wrap this in a function called makenewfoo() or something like this so I can invoke makenewfoo(foo) and allow this to create newfoo(). 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 this conditional-transformation expression before or after it (possibly using equal), 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)))