From: ·······@ai-cyclops.jpl.nasa.gov
Subject: Self-modifying function
Date: 
Message-ID: <11609@jpl-devvax.JPL.NASA.GOV>
I want to define a function that performs a certain computation on its first
invocation and performs a different computation on all subsequent invocations.
Consider the trivial (but representative) example below:

(defun mutate (list)
  (let ((len (length list)))
    (prog1 
      list
      (compile 'mutate
               `(lambda ()
                  ,len)))))

1> (mutate '(a b c))
=> (a b c)
2> (mutate '(a b c))
=> Error: too many arguments to function mutate.
3> (mutate)
=> 3

My question is, Will this function behave as expected (i.e., as described
above) in any Common LISP? More specifically, is it safe to modify the contents
of a symbols' function cell even as the contents are being executed? I can find
nothing in CLtL2 that addresses this. I welcome all opinions, learned or
otherwise.

-Len Charest
·······@ai-cyclops.jpl.nasa.gov

From: Barry Margolin
Subject: Re: Self-modifying function
Date: 
Message-ID: <1991Feb28.053846.1858@Think.COM>
In article <·····@jpl-devvax.JPL.NASA.GOV> ·······@ai-cyclops.jpl.nasa.gov writes:
>More specifically, is it safe to modify the contents
>of a symbols' function cell even as the contents are being executed?

I believe it is, but there are some rules.  CLtL doesn't address these
problems, but the X3J13 Compiler Committee did some work to tighten up this
area.  Here are relevant excerpts from the proposal that was approved:

    (b) The compiler may assume that, within a named function, a
	recursive call to a function of the same name refers to the
	same function, unless that function has been declared NOTINLINE.

    (c) COMPILE-FILE may assume that, in the absence of NOTINLINE
	declarations, a call within the file being compiled to a named
	function which is defined in that file refers to that function.
	(This permits "block compilation" of files.)  The behavior of
	the program is unspecified if functions are redefined individually 
	at runtime.

Point (b) is not directly applicable to your example, but it would be to a
modified version that ends with a recursive call to the function.

However, point (c) is applicable if there are calls to the function in
other parts of the file.

In both cases, preceding the definition with a (proclaim '(notinline
mutate)) should make things safe.
--
Barry Margolin, Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar
From: ·············@levels.sait.edu.au
Subject: Re: Self-modifying function
Date: 
Message-ID: <15983.27dfd64c@levels.sait.edu.au>
In article <·····@jpl-devvax.JPL.NASA.GOV>, ·······@ai-cyclops.jpl.nasa.gov writes:
> I want to define a function that performs a certain computation on its first
> invocation and performs a different computation on all subsequent invocations.
> Consider the trivial (but representative) example below:
> 
> (defun mutate (list)
>   (let ((len (length list)))
>     (prog1 
>       list
>       (compile 'mutate
>                `(lambda ()
>                   ,len)))))
> 
> 1> (mutate '(a b c))
> => (a b c)
> 2> (mutate '(a b c))
> => Error: too many arguments to function mutate.
> 3> (mutate)
> => 3
> 
> My question is, Will this function behave as expected (i.e., as described
> above) in any Common LISP? More specifically, is it safe to modify the contents
> of a symbols' function cell even as the contents are being executed? I can find
> nothing in CLtL2 that addresses this. I welcome all opinions, learned or
> otherwise.
> 
> -Len Charest
> ·······@ai-cyclops.jpl.nasa.gov


You could try something like:

(defun mutate (list)
  (let ((len (length list)))
    (setf (symbol-function 'mutate) #'(lambda () len))
    list))

I am not one for altering function definitions on the fly - but if one must,
this version seems 'nicer' than the other. I would welcome any comments on it
however.

-Jenny Rowland
·············@sait.edu.au