From: wm
Subject: Is this a bug (cmucl release-19a)
Date: 
Message-ID: <d3591234-861d-4067-85e3-8cb3d868d6a0@d19g2000prm.googlegroups.com>
in CMU Common Lisp CVS release-19a 19a-release-20040728 + minimal
debian patches
================================================
* (defun double (x) (* x 2))

DOUBLE
* (double 3)

6
* (setf (car (cddadr (cdaddr (function-lambda-expression #'double))))
4)

4
* (double 3)

6
*  (function-lambda-expression #'double)

(LAMBDA (X) (BLOCK DOUBLE (* X 4)))
NIL
DOUBLE
================================================

Why the second invocation of (double 3) still returns 6?

Here is what happen in clisp: GNU CLISP 2.42 (2007-10-16)
================================================
[1]> (defun double (x) (* x 2))
DOUBLE
[2]> (double 3)
6
[3]> (setf (cadr (cdaddr (cadddr (function-lambda-expression
#'double)))) 4)
4
[4]> (double 3)
12
================================================

From: Rainer Joswig
Subject: Re: Is this a bug (cmucl release-19a)
Date: 
Message-ID: <joswig-DBE3CD.00580706062008@news-europe.giganews.com>
In article 
<····································@d19g2000prm.googlegroups.com>,
 wm <······@gmail.com> wrote:

> in CMU Common Lisp CVS release-19a 19a-release-20040728 + minimal
> debian patches
> ================================================
> * (defun double (x) (* x 2))
> 
> DOUBLE
> * (double 3)
> 
> 6
> * (setf (car (cddadr (cdaddr (function-lambda-expression #'double))))
> 4)
> 
> 4
> * (double 3)
> 
> 6
> *  (function-lambda-expression #'double)
> 
> (LAMBDA (X) (BLOCK DOUBLE (* X 4)))
> NIL
> DOUBLE
> ================================================
> 
> Why the second invocation of (double 3) still returns 6?

It is not defined what happens if you change the
return value of (function-lambda-expression #'some-function) .


> 
> Here is what happen in clisp: GNU CLISP 2.42 (2007-10-16)
> ================================================
> [1]> (defun double (x) (* x 2))
> DOUBLE
> [2]> (double 3)
> 6
> [3]> (setf (cadr (cdaddr (cadddr (function-lambda-expression
> #'double)))) 4)
> 4
> [4]> (double 3)
> 12
> ================================================

-- 
http://lispm.dyndns.org/
From: wm
Subject: Re: Is this a bug (cmucl release-19a)
Date: 
Message-ID: <9ec6150c-6af7-471e-ba52-f5ee831f85aa@f24g2000prh.googlegroups.com>
On Jun 5, 3:58 pm, Rainer Joswig <······@lisp.de> wrote:
> In article
> <····································@d19g2000prm.googlegroups.com>,
>
>
>
>  wm <······@gmail.com> wrote:
> > in CMU Common Lisp CVS release-19a 19a-release-20040728 + minimal
> > debian patches
> > ================================================
> > * (defun double (x) (* x 2))
>
> > DOUBLE
> > * (double 3)
>
> > 6
> > * (setf (car (cddadr (cdaddr (function-lambda-expression #'double))))
> > 4)
>
> > 4
> > * (double 3)
>
> > 6
> > *  (function-lambda-expression #'double)
>
> > (LAMBDA (X) (BLOCK DOUBLE (* X 4)))
> > NIL
> > DOUBLE
> > ================================================
>
> > Why the second invocation of (double 3) still returns 6?
>
> It is not defined what happens if you change the
> return value of (function-lambda-expression #'some-function) .
>

As you can see, I was trying to play with the 'self-modifying' code in
lisp.

From what I read from the web, I need to use function-lambda-
expression to play the magic.
If its behavior is undefined by the CL standard, is there another
'standard' way I can do it?

Or is there any special command in CMUCL that can force the new
modification be used by subsequent function invocations?

Thanks.
From: Rainer Joswig
Subject: Re: Is this a bug (cmucl release-19a)
Date: 
Message-ID: <joswig-521DE2.01295106062008@news-europe.giganews.com>
In article 
<····································@f24g2000prh.googlegroups.com>,
 wm <······@gmail.com> wrote:

> On Jun 5, 3:58�pm, Rainer Joswig <······@lisp.de> wrote:
> > In article
> > <····································@d19g2000prm.googlegroups.com>,
> >
> >
> >
> > �wm <······@gmail.com> wrote:
> > > in CMU Common Lisp CVS release-19a 19a-release-20040728 + minimal
> > > debian patches
> > > ================================================
> > > * (defun double (x) (* x 2))
> >
> > > DOUBLE
> > > * (double 3)
> >
> > > 6
> > > * (setf (car (cddadr (cdaddr (function-lambda-expression #'double))))
> > > 4)
> >
> > > 4
> > > * (double 3)
> >
> > > 6
> > > * �(function-lambda-expression #'double)
> >
> > > (LAMBDA (X) (BLOCK DOUBLE (* X 4)))
> > > NIL
> > > DOUBLE
> > > ================================================
> >
> > > Why the second invocation of (double 3) still returns 6?
> >
> > It is not defined what happens if you change the
> > return value of (function-lambda-expression #'some-function) .
> >
> 
> As you can see, I was trying to play with the 'self-modifying' code in
> lisp.
> 
> From what I read from the web, I need to use function-lambda-
> expression to play the magic.
> If its behavior is undefined by the CL standard, is there another
> 'standard' way I can do it?
> 
> Or is there any special command in CMUCL that can force the new
> modification be used by subsequent function invocations?
> 
> Thanks.

You can create functions from lambda expressions by calling
EVAL or COMPILE. Compile can also set the symbol-function.
Otherwise use (setf (symbol-function 'double) (eval (lambda (x) (+ x 6)))) .


Examples (we redefine double to do something else...):

(compile 'double (lambda (x) (+ x x x)))


(setf (symbol-function 'double)
   (compile nil (lambda (x) (+ x x x))))

(setf (symbol-function 'double)
  (eval (lambda (x) (+ x x x))))

-- 
http://lispm.dyndns.org/
From: Alex Mizrahi
Subject: Re: Is this a bug (cmucl release-19a)
Date: 
Message-ID: <4849b038$0$90273$14726298@news.sunsite.dk>
 RJ> You can create functions from lambda expressions by calling
 RJ> EVAL or COMPILE. Compile can also set the symbol-function.
 RJ> Otherwise use (setf (symbol-function 'double) (eval (lambda (x) (+ x
 RJ> 6)))) .

probaly you mean (eval '(lambda ...))

also this can be done via (coerce '(lambda (x) ...) 'function) 
From: Alex Mizrahi
Subject: Re: Is this a bug (cmucl release-19a)
Date: 
Message-ID: <4849b6c2$0$90267$14726298@news.sunsite.dk>
 w> Why the second invocation of (double 3) still returns 6?

you have a wrong idea about how Common Lisp works. it's not specified that 
it
should evaluate s-expressions as it sees them, and indeed most 
implementations
out there do not do this -- they first transform expressions, optimizing 
them, and forming
some interal code representation like a bytecode or even native code.

function-lambda-expression is there for supplementary purposes like 
code-walking, debugging etc,
but not for direct manipulation of code. implementations are allowed to 
return NIL instead of function
definition, so this is not functionality to depend on, if you need 
portability.

 w> Here is what happen in clisp: GNU CLISP 2.42 (2007-10-16)

some implementaitons might indeed use s-expressions directly to execute 
code.

 w> As you can see, I was trying to play with the 'self-modifying' code in 
lisp.

Common Lisp does not particularly support self-modifying code, because this 
has very little practical sense -- it cannot be done efficiently.

most dynamic effects can be done via closures, it is really powerful tool, i 
strongly recommend you learning closure tricks.
e.g. thing you were trying to do:

(let ((factor 2))
  (defun double (x)
    (* x factor))
  (defun set-double-factor (y)
   (setf factor y)))

you can also change * to + this way:

(let ((operation #'*))
  (defun double (x)
    (funcall operation x 2))
  (defun set-double-operation (y)
    (setf operation y)))

then you can do (set-double-operation #'+) to use + instead of *.

so, you see, this way you can dynamically change _any_ aspects of code as 
long as you can foresee them.
doing unforeseen changes is barely practical.

other tools related to "self-modification" are macros/reader-time 
evaluation -- this way you can generate
code if you know it before run-time. and eval and run-time function 
generation -- this way you can generate
code you know only at run time.

it's pretty easy to make a wrapper functions that will work as you were 
expecting  function-lambda-expression  to work,
i've made this once, but this is just a toy :)
From: Alex Mizrahi
Subject: Re: Is this a bug (cmucl release-19a)
Date: 
Message-ID: <484a45bd$0$90268$14726298@news.sunsite.dk>
 AM> it's pretty easy to make a wrapper functions that will work as you were
 AM> expecting  function-lambda-expression  to work,
 AM> i've made this once, but this is just a toy :)

btw here it is -- i've defined defun-dynamic macro that memorizes function
body definition and allows to read it via function-body function,
and write it via (setf function-body).

so, for example, you can define function that adds two variables:

(defun-dynamic plus* (a b) (+ a b)) => ((+ A B))

(plus* 3 4) => 7

and then change + to -:

(setf (function-body plus*)
      (subst '- '+
             (function-body plus*)))
=> ((- A B))

(plus* 3 4) => -1

code can be found here: http://paste.lisp.org/display/53709
(and a bit different implementation that uses
funcallable-standard-object: http://paste.lisp.org/display/53714)

essential part is (setf function-body):

    (setf (symbol-function (function-name df))
          (coerce `(lambda ,(function-params df) ,@new-value) 'function)))

so it's just a thin wrapper around symbol-function and (coerce `(lambda ...) 
'function).