From: Willy
Subject: Dynamic change of main function??
Date: 
Message-ID: <94059dac.0307041802.3b974610@posting.google.com>
Hi,

I am learniing Lisp and know that one of its powerful feature is
supporting 'dynamic'. Meaning i can change program without stop it.

But I can't find much information on the net show me how this can be
done. So I try it myself, and I end up with a problem.

I defined few functions:
====
(defun f1 (x)
  (format t "New Counter = ~A~%" x))

(defun g1 (x)
  (format t "(in g1) New Counter = ~A~%" x))


(defun f2 (x)
  (if (= x 0)
      'done
    (progn (f1 x)
           (sleep 3)
           (f2 (- x 1)))))
====

and I run (I am using OpenMCL)

? (f2 10)
New Counter = 10
New Counter = 9
^C> Break: 
> While executing: #<Anonymous Function #x50F1996>
> Type :GO to continue, :POP to abort.
> If continued: Return from BREAK.
Type :? for other options.
1 > 


=== 
after I break it, I try to change the function (f2), instead of
calling (f1), to call (g1). And ask to continue. But the program
doesn't call (g1) , it still calling (f1).

However, if I change the content of (f1), the effect will immediate
appear.

So my quesiton is, can I dynamic change a 'running' function? Or I can
only change content of function which is not running?


Thanks.
Willie

From: Nick Levine
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <8732fc48.0307050009.6a1eaa46@posting.google.com>
Good morning.

> (defun f2 (x)
>   (if (= x 0)
>       'done
>     (progn (f1 x)
>            (sleep 3)
>            (f2 (- x 1)))))

[...]

> after I break it, I try to change the function (f2), instead of
> calling (f1), to call (g1). And ask to continue. But the program
> doesn't call (g1) , it still calling (f1).

Function f2 is "tail recursive", which means that a good compiler will
be able to transform the function, replacing the recursive calls with
a loop, like this:

(defun f2 (x)
  (loop
    (if (= x 0)
        (return-from f2 'done)
      (progn (f1 x)
             (sleep 3)
             (setf x (- x 1))))))

So redefining f2 while this is running won't have any effect, because
f2 no longer calls itself. On the other hand, if instead you have:

(defun f3 (x)
  (if (= x 0)
      0          ; done
    (progn (f1 x)
           (sleep 3)
           (- (f3 (- x 1)) 1))))

then the call from f3 to itself is not a tail-call and is not
optimised by the compiler into a loop ... and so in this case you can
redefine f3 "while it is running".

I can't locate anything in the spec that says when a compiler is
allowed to make transforms like this. (Doesn't mean it's not there,
just that I can't find it.) It might be that your implementation will
respond to some optimization quality as an instruction not to
transform - you'll have to check your documentation for that.

(defun f2 (x)
  (declare (optimize (debug 3)))
  (if (= x 0)
      'done
    (progn (f1 x)
           (sleep 3)
           (f2 (- x 1)))))

I googled on this subject to locate some introductory words from
someone who's more awake than I am. See
http://www.cis.ksu.edu/VirtualHelp/Info/develop/cmu-user.info.Tail_Recursion.html
for some words on tail recursion (from the CMU manual).

-nick
From: Alexey Dejneka
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <m3wuex8d6y.fsf@comail.ru>
Hello,

···@ravenbrook.com (Nick Levine) writes:

> Good morning.
> 
> > (defun f2 (x)
> >   (if (= x 0)
> >       'done
> >     (progn (f1 x)
> >            (sleep 3)
> >            (f2 (- x 1)))))
> 
> [...]
> 
> > after I break it, I try to change the function (f2), instead of
> > calling (f1), to call (g1). And ask to continue. But the program
> > doesn't call (g1) , it still calling (f1).
> 
> Function f2 is "tail recursive", which means that a good compiler will
                       ^^^^^^^^^

The call is probably in the tail position, but is not quite evident,
that it is recursive (see below).

> be able to transform the function, replacing the recursive calls with
> a loop, like this:
> 
> (defun f2 (x)
>   (loop
>     (if (= x 0)
>         (return-from f2 'done)
>       (progn (f1 x)
>              (sleep 3)
>              (setf x (- x 1))))))
> 
> So redefining f2 while this is running won't have any effect, because
> f2 no longer calls itself.

It F2 calls itself, it hardly can be redefined. It should call a
function, named at the time of call by the symbol F2.

> On the other hand, if instead you have:
> 
> (defun f3 (x)
>   (if (= x 0)
>       0          ; done
>     (progn (f1 x)
>            (sleep 3)
>            (- (f3 (- x 1)) 1))))
> 
> then the call from f3 to itself is not a tail-call and is not
> optimised by the compiler into a loop ... and so in this case you can
> redefine f3 "while it is running".

CLHS 3.2.2.3 Semantic Constraints:

  Within a function named F, the compiler may (but is not required to)
  assume that an apparent recursive call to a function named F refers
  to the same definition of F, unless that function has been declared
  notinline. The consequences of redefining such a recursively defined
  function F while it is executing are undefined.

So a (don't know about "the") compiler may implement the call of F3 as
a "direct call", preventing dynamic redefinition. The portable way to
allow redefinition is to wrap a possibly recursive call into (LOCALLY
(DECLARE (NOTINLINE F3)) ...).

-- 
Regards,
Alexey Dejneka

"Alas, the spheres of truth are less transparent than those of
illusion." -- L.E.J. Brouwer
From: Willy
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <94059dac.0307050640.5eccfda@posting.google.com>
Hi everyone,

Thanks for all your replies.

So until now, if I understand correctly, a 'running direct function'
cannot be dynamically redefined but a recursive function can if they
are not optimize by the compiler becaues of tail-recursive and if they
are declared notinline.

Am I right?

> CLHS 3.2.2.3 Semantic Constraints:
> 
>   Within a function named F, the compiler may (but is not required to)
>   assume that an apparent recursive call to a function named F refers
>   to the same definition of F, unless that function has been declared
>   notinline. The consequences of redefining such a recursively defined
>   function F while it is executing are undefined.
> 
> So a (don't know about "the") compiler may implement the call of F3 as
> a "direct call", preventing dynamic redefinition. The portable way to
> allow redefinition is to wrap a possibly recursive call into (LOCALLY
> (DECLARE (NOTINLINE F3)) ...).
From: Kenny Tilton
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <3F0652CD.7070102@nyc.rr.com>
Willy wrote:
> Hi,
> 
> I am learniing Lisp and know that one of its powerful feature is
> supporting 'dynamic'. Meaning i can change program without stop it.
> 
> But I can't find much information on the net show me how this can be
> done. So I try it myself, and I end up with a problem.
> 
> I defined few functions:
> ====
> (defun f1 (x)
>   (format t "New Counter = ~A~%" x))
> 
> (defun g1 (x)
>   (format t "(in g1) New Counter = ~A~%" x))
> 
> 
> (defun f2 (x)
>   (if (= x 0)
>       'done
>     (progn (f1 x)
>            (sleep 3)
>            (f2 (- x 1)))))
> ====
> 
> and I run (I am using OpenMCL)
> 
> ? (f2 10)
> New Counter = 10
> New Counter = 9
> ^C> Break: 
> 
>>While executing: #<Anonymous Function #x50F1996>
>>Type :GO to continue, :POP to abort.
>>If continued: Return from BREAK.
> 
> Type :? for other options.
> 1 > 
> 
> 
> === 
> after I break it, I try to change the function (f2), instead of
> calling (f1), to call (g1). And ask to continue. But the program
> doesn't call (g1) , it still calling (f1).
> 
> However, if I change the content of (f1), the effect will immediate
> appear.
> 
> So my quesiton is, can I dynamic change a 'running' function? Or I can
> only change content of function which is not running?

Right (if I understand you). The new definition takes hold the next time 
it is /entered/. Now I see that source-wise you would recursively enter 
f2 after continuing, but (and here I am guessing wildly) I note that the 
recursive call is in a tail position, so maybe the compiler has 
optimized away the recursive entry into f2. ie, the machine code is 
iterating within a single /ongoing/ call of the orginal f2.

this wild guessing is supported nicely by the observed behavior, btw. :)

-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Everything is a cell." -- Alan Kay
From: Kaz Kylheku
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <cf333042.0307050833.546aa0a@posting.google.com>
··········@yahoo.com (Willy) wrote in message news:<····························@posting.google.com>...
> after I break it, I try to change the function (f2), instead of
> calling (f1), to call (g1). And ask to continue. But the program
> doesn't call (g1) , it still calling (f1).
>
> However, if I change the content of (f1), the effect will immediate
> appear.
> 
> So my quesiton is, can I dynamic change a 'running' function? Or I can
> only change content of function which is not running?

Common Lisp's dynamic function redefinition is not a form of
self-modifying code! A function is an object. When you redefine a
function, you are creating a new function object and pointing the
function-binding of the symbol to that new object. New calls to the
function, through the symbol, go to the new definition.

What happened in your program is that you suspended the execution of
the old version of F2, and while it was suspended, you created a new
function and associated that with the name F2. But this has no effect
on the existing activations of the old function, which will continue
to refer to the old body. When the program loses all references to the
old function, it will be garbage collected. References to the old
function may be captured not only in existing activations of that
function, but in variable references as well. E.g.

  (let ((always-old-f2 #'f2)
        (always-current-f2 'f2))
    (loop
      (funcall always-old-f2 args ...)
      (funcall always-current-f2 args ...)))

Calling through the F2 *symbol* gets you the latest. Calling through a
reference to the object itself, obtained by evaluating #'F2, will call
the same object. But of course re-evaluating the expression #'F2 after
F2 is redefined will also yield the new object.

This method of modifying running software is reasonably safe and
manageable, to the point that you can incorporate it into the logic of
an application running in the field.

Imagine you have a multithreaded program, and you modify some code
while threads are runnig it. It could be a disaster.
From: Kalle Olavi Niemitalo
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <87znjshpyu.fsf@Astalo.kon.iki.fi>
···@ashi.footprints.net (Kaz Kylheku) writes:

> When the program loses all references to the old function, it
> will be garbage collected. References to the old function may
> be captured not only in existing activations of that function,
> but in variable references as well.

How do the garbage collectors of CL implementations usually know
which functions are active and must not be collected?

Compiled C code typically saves a return address on a stack when
it calls a function.  Does Lisp code additionally save a pointer
to the calling function, so that the garbage collector can use
that as a root?  Or does the garbage collector recognize the
function from the return address?
From: Kaz Kylheku
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <cf333042.0307071158.786f9f12@posting.google.com>
··········@yahoo.com (Willy) wrote in message news:<···························@posting.google.com>...
> Thanks Kaz Kylheku. I understand the concept now.
> 
> Does this mean if I want to have a dynamic changable function, I must
> always put it onto the 'second level' and call it with a loop.

The loop is just an example; no loop has to be involved. You wrote
that you were re-defining functions manually, while a loop is
suspended, so I tailored the example to that mode of experimentation.

> But what if I want to change 'first level' of fucntion (just after
> read-eval-loop)? Can I do it inside the debugger?

Not sure what you mean by these first and second levels.
From: Thomas F. Burdick
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <xcvel12av7g.fsf@famine.OCF.Berkeley.EDU>
··········@yahoo.com (Willy) writes:

> Thanks Kaz Kylheku. I understand the concept now.
>
> Does this mean if I want to have a dynamic changable function, I must
> always put it onto the 'second level' and call it with a loop.
>
> But what if I want to change 'first level' of fucntion (just after
> read-eval-loop)? Can I do it inside the debugger?

I think I get what you mean here.  No, you can't, because although
Lisp allows you to redefine functions, it doesn't mutate existing
function objects.  This is a time when a picture is probably worth
1000 words.  If you do the following:

  * (defun foo ()
      (print "Starting FOO...")
      (bar)
      (print "Ending FOO...")
      nil)

  FOO
  * (defun bar ()
      (print "Starting BAR...")
      (force-output *standard-output*) ; flush the buffer
      (break) ; enter the debugger
      (print "Ending BAR..."))

  BAR
  * (foo)

  "Starting FOO..."
  "Starting BAR..."

  Break

  Restarts:
    0: [CONTINUE] Return from BREAK.
    1: [ABORT   ] Return to Top-Level.

  Debug  (type H for help)

  (BAR)
  Source: (BREAK)
  0]

Then the world looks something like this:

 +---------------------+
 |    repl-function    |
 |[... machine code...]|
 +--------|------------+
          |
          +----------> +--------------------+
 #<The Symbol FOO>---> |    foo-function    |
                       |[...machine code...]|
                       +-------|------------+
                               |
                               +----------->+--------------------+
                       #<The Symbol BAR>--->|    bar-function    |
                                            |[...machine code...]|
                                            +-------|------------+
                                                    |
                                                    +-----> Debugger


You can, in the debugger, define a new function named FOO:

  0] (defun foo ()
       (print "Starting new FOO...")
       (bar)
       (print "Ending new FOO...")
       nil)
  Converted FOO.
  FOO

Now the world looks like this:

 +---------------------+
 |    repl-function    |
 |[... machine code...]|
 +--------|------------+
          |
          +----------> +--------------------+
 #<The FOO Symbol>-+   |  old-foo-function  |
                   |   |[...machine code...]|
                   |   +-------|------------+
                   |           |
                   |           +----------->+--------------------+
                   |   #<The BAR Symbol>--->|    bar-function    |
                   |                        |[...machine code...]|
                   V                        +-------|------------+
                   +--------------------+           |
                   |  new-foo-function  |           +-----> Debugger
                   |[...machine code...]|
                   +--------------------+

So, the next time someone looks for the function named by FOO, they'll
find the new-foo-function object.  However, old references to the
old-foo-function object arren't modified, so the control stack isn't
changed.

  0] :continue

  "Ending BAR..."
  "Ending FOO..."
  NIL
  * (foo)

  "Starting new FOO..."
  "Starting BAR..."

  Break

  Restarts:
    0: [CONTINUE] Return from BREAK.
    1: [ABORT   ] Return to Top-Level.

  Debug  (type H for help)

  (BAR)
  Source: (BREAK)
  0] :continue

  "Ending BAR..."
  "Ending new FOO..."
  NIL


--
           /|_     .-----------------------.
         ,'  .\  / | No to Imperialist war |
     ,--'    _,'   | Wage class war!       |
    /       /      `-----------------------'
   (   -.  |
   |     ) |
  (`-.  '--.)
   `. )----'
From: Kent M Pitman
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <sfwvfuddgjc.fsf@shell01.TheWorld.com>
···@famine.OCF.Berkeley.EDU (Thomas F. Burdick) writes:

> ··········@yahoo.com (Willy) writes:
> 
> > Thanks Kaz Kylheku. I understand the concept now.
> >
> > Does this mean if I want to have a dynamic changable function, I must
> > always put it onto the 'second level' and call it with a loop.
> >
> > But what if I want to change 'first level' of fucntion (just after
> > read-eval-loop)? Can I do it inside the debugger?
> 
> I think I get what you mean here.  No, you can't, because although
> Lisp allows you to redefine functions, it doesn't mutate existing
> function objects.

Yes and no.

In some debuggers you can find the (outer or "level 1") FOO frame 
and do

  :RETURN      <-- or some other command meaning "return from this frame"

and get prompted for a value [in some debuggers the value might go on
the same line as the :RET or :RETURN command] 


  Return what value?

In either case, the value you want to return is
the result of evaluating:   (FOO)

That is, you can substitute a new function call on the stack by calling
FOO anew.  It helps a lot if FOO is easy to call.  If FOO is called with
a dozen hard to conjure arguments, then you may have to do something
like (SETQ TEMP1 ...grab first arg from local env... TEMP2 ...etc..)
and then something like (FOO TEMP1 TEMP2 TEMP3 :key1 TEMP4 :key2 TEMP5 ...).

In some debuggers, there is a very helpful synonym for this particular
call which is

  :RETRY

which tells the compiler to go re-invoke the indicated function.  The thing
you need to be sure is that the compiler is going to re-lookup the function,
but this is an obvious thing to want and if it doesn't do this, talk to
the implementors.
From: Willy
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <94059dac.0307090217.76708969@posting.google.com>
Cool. This is what I am looking for (:RETRY)...

Thanks very much!!!


Kent M Pitman <······@world.std.com> wrote in message news:<···············@shell01.TheWorld.com>...
> ···@famine.OCF.Berkeley.EDU (Thomas F. Burdick) writes:
> 
> > ··········@yahoo.com (Willy) writes:
> > 
> > > Thanks Kaz Kylheku. I understand the concept now.
> > >
> > > Does this mean if I want to have a dynamic changable function, I must
> > > always put it onto the 'second level' and call it with a loop.
> > >
> > > But what if I want to change 'first level' of fucntion (just after
> > > read-eval-loop)? Can I do it inside the debugger?
> > 
> > I think I get what you mean here.  No, you can't, because although
> > Lisp allows you to redefine functions, it doesn't mutate existing
> > function objects.
> 
> Yes and no.
> 
> In some debuggers you can find the (outer or "level 1") FOO frame 
> and do
> 
>   :RETURN      <-- or some other command meaning "return from this frame"
> 
> and get prompted for a value [in some debuggers the value might go on
> the same line as the :RET or :RETURN command] 
> 
> 
>   Return what value?
> 
> In either case, the value you want to return is
> the result of evaluating:   (FOO)
> 
> That is, you can substitute a new function call on the stack by calling
> FOO anew.  It helps a lot if FOO is easy to call.  If FOO is called with
> a dozen hard to conjure arguments, then you may have to do something
> like (SETQ TEMP1 ...grab first arg from local env... TEMP2 ...etc..)
> and then something like (FOO TEMP1 TEMP2 TEMP3 :key1 TEMP4 :key2 TEMP5 ...).
> 
> In some debuggers, there is a very helpful synonym for this particular
> call which is
> 
>   :RETRY
> 
> which tells the compiler to go re-invoke the indicated function.  The thing
> you need to be sure is that the compiler is going to re-lookup the function,
> but this is an obvious thing to want and if it doesn't do this, talk to
> the implementors.
From: Barry Margolin
Subject: Re: Dynamic change of main function??
Date: 
Message-ID: <64gOa.6$Vb2.2@news.level3.com>
In article <···························@posting.google.com>,
Willy <··········@yahoo.com> wrote:
>Thanks Kaz Kylheku. I understand the concept now.
>
>Does this mean if I want to have a dynamic changable function, I must
>always put it onto the 'second level' and call it with a loop.

No.  But *if* you call it recursively, you need to use the NOTINLINE
declaration to prevent an optimization that prevents the new definition
from being used.

>But what if I want to change 'first level' of fucntion (just after
>read-eval-loop)? Can I do it inside the debugger?

If you call it from the top-level, you should always get the updated
function binding.

-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.