From: Stefan Kamphausen
Subject: Dynamic function bindings
Date: 
Message-ID: <1137762923.743356.36700@z14g2000cwz.googlegroups.com>
Hi,

first I hope I got the subject right: I think I am looking for a way to
dynamically bind functions just the way I can do it with dynamic
variables.

Using vars it works like this

  (defparameter *dynamic* "Hello")

  (defun test-it ()
    (print *dynamic*)
    (let ((*dynamic* "World"))
      (print *dynamic*)))

... everybody knows this.

It also works to locally override a globally defined function:

  (defun dynamicornot ()
    (format t "Am I dynamic?~%"))

  (defun test-it-2 ()
    (dynamicornot)
    (flet ((dynamicornot ()
             (format t "yes! I am~%")))
      (dynamicornot))
    (dynamicornot))

  CL-USER> (test-it-2)
  Am I dynamic?
  yes! I am
  Am I dynamic?

No what I'd like to have is to dynamically rebind a function that is
called somewhere down the stack:


  ;; low level function that should be rebound
  (defun rebindme ()
    (format t "Rebind me, please~%"))

  ;; higher level function which calls the low level defun
  (defun test-rebinding ()
    (format t "test-rebinding calls rebindme~%")
    (rebindme))

  ;; test function that should locally override the low level function
  (defun can-not-rebind-it ()
    (test-rebinding)
    (flet ((rebindme ()
             (format t "This get's deleted by compiler~%")))
      (test-rebinding))
    (test-rebinding))

As you can see if you compile it the flet'ed function get's deleted and
consequently the sample session looks like this:

  CL-USER> (can-not-rebind-it)
  test-rebinding calls rebindme
  Rebind me, please
  test-rebinding calls rebindme
  Rebind me, please
  test-rebinding calls rebindme
  Rebind me, please
  NIL
  CL-USER>

I need this to test some higher level functions that interact with a
complex system somewhere down the stack without that comlex system
actually running.  

Kind regards,
Stefan Kamphausen

From: Edi Weitz
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <u4q3zghfg.fsf@agharta.de>
On 20 Jan 2006 05:15:23 -0800, "Stefan Kamphausen" <······@gmx.de> wrote:

> I think I am looking for a way to dynamically bind functions just
> the way I can do it with dynamic variables.

Pascal Costanza has done some work on this:

  <http://citeseer.ist.psu.edu/719047.html>

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Pascal Bourguignon
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <87d5imirex.fsf@thalassa.informatimago.com>
Edi Weitz <········@agharta.de> writes:
> On 20 Jan 2006 05:15:23 -0800, "Stefan Kamphausen" <······@gmx.de> wrote:
>
>> I think I am looking for a way to dynamically bind functions just
>> the way I can do it with dynamic variables.
>
> Pascal Costanza has done some work on this:
>
>   <http://citeseer.ist.psu.edu/719047.html>

Something like:

(defmacro dflet (fdefs &body body)
  (if (null fdefs)
      `(progn ,@body)
      `(let ((old-function (fdefinition ',(caar fdefs))))
         (setf (fdefinition  ',(caar fdefs))
               (lambda ,(cadar fdefs)
                 (flet ((call-next-function (&rest args)
                          (apply old-function args)))
                   (block ,(if (consp (caar fdefs))
                               (cadaar fdefs)
                               (caar fdefs))
                     ,@(cddar fdefs)))))
         (unwind-protect
              (dflet ,(cdr fdefs) ,@body)
           (setf (fdefinition ',(caar fdefs)) old-function)))))

;; handling of (call-next-function) without arguments left as an
;; exercise to the reader ;-)


(defun f (x) (print x))
(dflet ((f (x)
           (print "entering f")
           (call-next-function x)
           (print "leaving f")))
       (f 5))

"entering f" 
5 
"leaving f" 


(defun (setf premier) (v c) (setf (car c) v))
(dflet (((setf premier) (v c)
           (print "entering (setf premier)")
           (call-next-function v c)
           (print "leaving (setf premier)")))
     (let ((a (cons 1 2)))
       (setf (premier a) 5)
       (print a)))

"entering (setf premier)" 
"leaving (setf premier)" 
(5 . 2) 


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

What is this talk of 'release'? Klingons do not make software 'releases'.
Our software 'escapes' leaving a bloody trail of designers and quality
assurance people in it's wake.
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <87acdqefnj.fsf@qrnik.zagroda>
Pascal Bourguignon <····@mouse-potato.com> writes:

> (defmacro dflet (fdefs &body body)
>   (if (null fdefs)
>       `(progn ,@body)
>       `(let ((old-function (fdefinition ',(caar fdefs))))
>          (setf (fdefinition  ',(caar fdefs))
>                (lambda ,(cadar fdefs)
>                  (flet ((call-next-function (&rest args)
>                           (apply old-function args)))
>                    (block ,(if (consp (caar fdefs))
>                                (cadaar fdefs)
>                                (caar fdefs))
>                      ,@(cddar fdefs)))))
>          (unwind-protect
>               (dflet ,(cdr fdefs) ,@body)
>            (setf (fdefinition ',(caar fdefs)) old-function)))))

This doesn't have the intended semantics in multiple threads.

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: Pascal Costanza
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43ib36F1mhe86U1@individual.net>
Edi Weitz wrote:
> On 20 Jan 2006 05:15:23 -0800, "Stefan Kamphausen" <······@gmx.de> wrote:
> 
>>I think I am looking for a way to dynamically bind functions just
>>the way I can do it with dynamic variables.
> 
> Pascal Costanza has done some work on this:
> 
>   <http://citeseer.ist.psu.edu/719047.html>

Thanks a lot for mentioning it, but this is actually not among my 
preferred papers about the subject.

The section about "context-oriented programming" at 
http://p-cos.net/research.html contains three papers that all show 
variations on how to apply dynamic scoping to concepts other than 
variables. The paper about AspectL in the "aspect-oriented programming" 
section also talks about "special generic functions", just another 
variation.

I am not working on AspectL anymore, for several reasons. Instead, check 
out ContextL and the paper about dynamically scoped functions (which 
includes working code). ContextL provides almost all the features of 
AspectL, but in cleaner and more efficient ways (and it drops the only 
"real" AOP feature of AspectL). Dynamically scoped functions 
should/could be useful for small things and playing around with the idea...


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: David Sletten
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <McbAf.1110$Z3.1092@tornado.socal.rr.com>
Stefan Kamphausen wrote:

> Hi,
> 
> first I hope I got the subject right: I think I am looking for a way to
> dynamically bind functions just the way I can do it with dynamic
> variables.
> 
> Using vars it works like this
> 
>   (defparameter *dynamic* "Hello")
> 
>   (defun test-it ()
>     (print *dynamic*)
>     (let ((*dynamic* "World"))
>       (print *dynamic*)))
> 
> ... everybody knows this.
> 
> It also works to locally override a globally defined function:
> 
>   (defun dynamicornot ()
>     (format t "Am I dynamic?~%"))
> 
>   (defun test-it-2 ()
>     (dynamicornot)
>     (flet ((dynamicornot ()
>              (format t "yes! I am~%")))
>       (dynamicornot))
>     (dynamicornot))
> 
>   CL-USER> (test-it-2)
>   Am I dynamic?
>   yes! I am
>   Am I dynamic?
> 
> No what I'd like to have is to dynamically rebind a function that is
> called somewhere down the stack:
> 
> 
>   ;; low level function that should be rebound
>   (defun rebindme ()
>     (format t "Rebind me, please~%"))
> 
>   ;; higher level function which calls the low level defun
>   (defun test-rebinding ()
>     (format t "test-rebinding calls rebindme~%")
>     (rebindme))
> 
>   ;; test function that should locally override the low level function
>   (defun can-not-rebind-it ()
>     (test-rebinding)
>     (flet ((rebindme ()
>              (format t "This get's deleted by compiler~%")))
>       (test-rebinding))
>     (test-rebinding))
> 
> As you can see if you compile it the flet'ed function get's deleted and
> consequently the sample session looks like this:
> 
>   CL-USER> (can-not-rebind-it)
>   test-rebinding calls rebindme
>   Rebind me, please
>   test-rebinding calls rebindme
>   Rebind me, please
>   test-rebinding calls rebindme
>   Rebind me, please
>   NIL
>   CL-USER>
> 
> I need this to test some higher level functions that interact with a
> complex system somewhere down the stack without that comlex system
> actually running.  
> 
> Kind regards,
> Stefan Kamphausen
> 

This may not be _exactly_ what you want, but there seems to be one 
obvious solution:

* (defvar *rebindme* #'rebindme)

*REBINDME*

* (defun test-rebinding () 

     (format t "test-rebinding calls rebindme~%") 

     (funcall *rebindme*))

TEST-REBINDING
* (defun can-rebind-it ()
     (test-rebinding) 

       (let ((*rebindme* #'(lambda () (format t "I feel like a new 
                      function!~%"))))
         (test-rebinding)) 

       (test-rebinding))

CAN-REBIND-IT
* (can-rebind-it)
test-rebinding calls rebindme
Rebind me, please
test-rebinding calls rebindme
I feel like a new function!
test-rebinding calls rebindme
Rebind me, please
NIL


This may be awkward if you need to dynamically bind many functions.

Aloha,
David Sletten
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d183ac$0$87291$5a6aecb4@news.aaisp.net.uk>
On 2006-01-20 13:15:23 +0000, "Stefan Kamphausen" <······@gmx.de> said:

> As you can see if you compile it the flet'ed function get's deleted and
> consequently the sample session looks like this:
> 
>   CL-USER> (can-not-rebind-it)
>   test-rebinding calls rebindme
>   Rebind me, please
>   test-rebinding calls rebindme
>   Rebind me, please
>   test-rebinding calls rebindme
>   Rebind me, please
>   NIL
>   CL-USER>
> 
> I need this to test some higher level functions that interact with a
> complex system somewhere down the stack without that comlex system
> actually running.

What would be wrong with:

(defun rebind-me ()
  (format t "rebind me~%"))

(defun test ()
  (let ((old (symbol-function 'rebind-me)))
    (rebind-me)
    (setf (symbol-function 'rebind-me) (lambda () (format t "rebound!~%")))
    (rebind-me)
    (setf (symbol-function 'rebind-me) old)
    (rebind-me)))


CL-USER 5 > (test)
rebind me
rebound!
rebind me
NIL

?
--
JFB
From: Pascal Bourguignon
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <87wtgufliz.fsf@thalassa.informatimago.com>
verec <·····@mac.com> writes:
> On 2006-01-20 13:15:23 +0000, "Stefan Kamphausen" <······@gmx.de> said:
>
>> As you can see if you compile it the flet'ed function get's deleted and
>> consequently the sample session looks like this:
>>   CL-USER> (can-not-rebind-it)
>>   test-rebinding calls rebindme
>>   Rebind me, please
>>   test-rebinding calls rebindme
>>   Rebind me, please
>>   test-rebinding calls rebindme
>>   Rebind me, please
>>   NIL
>>   CL-USER>
>> I need this to test some higher level functions that interact with a
>> complex system somewhere down the stack without that comlex system
>> actually running.
>
> What would be wrong with:
>
> (defun rebind-me ()
>   (format t "rebind me~%"))
>
> (defun test ()
>   (let ((old (symbol-function 'rebind-me)))
>     (rebind-me)
>     (setf (symbol-function 'rebind-me) (lambda () (format t "rebound!~%")))
>     (rebind-me)
>     (setf (symbol-function 'rebind-me) old)
>     (rebind-me)))
>
>
> CL-USER 5 > (test)
> rebind me
> rebound!
> rebind me
> NIL

The same as with my solution: if there is another thread, it'll see
the changed dynamic binding.  

Worse than with my solution: if there's an error or an interruption
between the two setf symbol-function, the rebound binding will be
left.  At least you should use UNWIND-PROTECT!

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"Our users will know fear and cower before our software! Ship it!
Ship it and let them flee like the dogs they are!"
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d18876$0$87291$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 00:54:28 +0000, Pascal Bourguignon <····@mouse-potato.com> said:

>> What would be wrong with:
>> 
>> (defun rebind-me ()
>> (format t "rebind me~%"))
>> 
>> (defun test ()
>> (let ((old (symbol-function 'rebind-me)))
>> (rebind-me)
>> (setf (symbol-function 'rebind-me) (lambda () (format t "rebound!~%")))
>> (rebind-me)
>> (setf (symbol-function 'rebind-me) old)
>> (rebind-me)))
>> 
>> 
>> CL-USER 5 > (test)
>> rebind me
>> rebound!
>> rebind me
>> NIL
> 
> The same as with my solution: if there is another thread, it'll see
> the changed dynamic binding.
> Worse than with my solution: if there's an error or an interruption
> between the two setf symbol-function, the rebound binding will be
> left.  At least you should use UNWIND-PROTECT!

OK, Point taken. Still not thread safe but:

(defun test2 ()
  (rebind-me)
  (let ((old (symbol-function 'rebind-me)))
    (unwind-protect
        (progn
          (setf (symbol-function 'rebind-me) (lambda () (format t 
"rebound!~%")))
          (rebind-me))
      (progn
        (setf (symbol-function 'rebind-me) old)
        (rebind-me)))))
--
JFB
From: Ron Garret
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <rNOSPAMon-CD47AA.18561620012006@news.gha.chartermi.net>
In article <·························@news.aaisp.net.uk>,
 verec <·····@mac.com> wrote:

> On 2006-01-21 00:54:28 +0000, Pascal Bourguignon <····@mouse-potato.com> said:
> 
> >> What would be wrong with:
> >> 
> >> (defun rebind-me ()
> >> (format t "rebind me~%"))
> >> 
> >> (defun test ()
> >> (let ((old (symbol-function 'rebind-me)))
> >> (rebind-me)
> >> (setf (symbol-function 'rebind-me) (lambda () (format t "rebound!~%")))
> >> (rebind-me)
> >> (setf (symbol-function 'rebind-me) old)
> >> (rebind-me)))
> >> 
> >> 
> >> CL-USER 5 > (test)
> >> rebind me
> >> rebound!
> >> rebind me
> >> NIL
> > 
> > The same as with my solution: if there is another thread, it'll see
> > the changed dynamic binding.
> > Worse than with my solution: if there's an error or an interruption
> > between the two setf symbol-function, the rebound binding will be
> > left.  At least you should use UNWIND-PROTECT!
> 
> OK, Point taken. Still not thread safe but:
> 
> (defun test2 ()
>   (rebind-me)
>   (let ((old (symbol-function 'rebind-me)))
>     (unwind-protect
>         (progn
>           (setf (symbol-function 'rebind-me) (lambda () (format t 
> "rebound!~%")))
>           (rebind-me))
>       (progn
>         (setf (symbol-function 'rebind-me) old)
>         (rebind-me)))))
> --
> JFB

Nope, that's not thread safe either.  You're not rebinding, you're just 
assigning to the existing binding.  The only way to do this correctly is 
to redefine the function so that it funcalls a function stored in the 
value cell of a special variable and then rebind that special.

rg
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d1ae9a$0$87294$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 02:56:17 +0000, Ron Garret <·········@flownet.com> said:

>> OK, Point taken. Still not thread safe but:
>> 
>> (defun test2 ()
>> (rebind-me)
>> (let ((old (symbol-function 'rebind-me)))
>> (unwind-protect
>> (progn
>> (setf (symbol-function 'rebind-me) (lambda () (format t "rebound!~%")))
>> (rebind-me))
>> (progn
>> (setf (symbol-function 'rebind-me) old)
>> (rebind-me)))))
> 
> Nope, that's not thread safe either.

Well, first I did say so at the top, and second
I posted a second version which I beleive is
thread and condition safe.

> You're not rebinding, you're just assigning to the existing binding.  
> The only way to do this correctly is to redefine the function so that 
> it funcalls a function stored in the value cell of a special variable 
> and then rebind that special.

This is a bit confusing. What would be the _observable difference_
between what you suggest and what I have been proposing?
--
JFB
From: Ron Garret
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <rNOSPAMon-C83CDA.23065020012006@news.gha.chartermi.net>
In article <·························@news.aaisp.net.uk>,
 verec <·····@mac.com> wrote:

> On 2006-01-21 02:56:17 +0000, Ron Garret <·········@flownet.com> said:
> 
> >> OK, Point taken. Still not thread safe but:
> >> 
> >> (defun test2 ()
> >> (rebind-me)
> >> (let ((old (symbol-function 'rebind-me)))
> >> (unwind-protect
> >> (progn
> >> (setf (symbol-function 'rebind-me) (lambda () (format t "rebound!~%")))
  *** here ***
> >> (rebind-me))
> >> (progn
> >> (setf (symbol-function 'rebind-me) old)
> >> (rebind-me)))))
> > 
> > Nope, that's not thread safe either.
> 
> Well, first I did say so at the top, and second
> I posted a second version which I beleive is
> thread and condition safe.
> 
> > You're not rebinding, you're just assigning to the existing binding.  
> > The only way to do this correctly is to redefine the function so that 
> > it funcalls a function stored in the value cell of a special variable 
> > and then rebind that special.
> 
> This is a bit confusing. What would be the _observable difference_
> between what you suggest and what I have been proposing?
> --
> JFB

If you have a context switch at the position indicated then the thread 
you switch to will see the "rebound" value.

You are making a very common mistake, not understanding the difference 
between rebinding and reassignment.  Read 
http://www.flownet.com/ron/specials.pdf.

rg
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d1e30a$0$87298$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 07:06:50 +0000, Ron Garret <·········@flownet.com> said:

> In article <·························@news.aaisp.net.uk>,
>  verec <·····@mac.com> wrote:
> 
>> On 2006-01-21 02:56:17 +0000, Ron Garret <·········@flownet.com> said:
>> 
>>>> OK, Point taken. Still not thread safe but:
>>>> 
>>>> (defun test2 ()
>>>> (rebind-me)
>>>> (let ((old (symbol-function 'rebind-me)))
>>>> (unwind-protect
>>>> (progn
>>>> (setf (symbol-function 'rebind-me) (lambda () (format t "rebound!~%")))
>   *** here ***
>>>> (rebind-me))
>>>> (progn
>>>> (setf (symbol-function 'rebind-me) old)
>>>> (rebind-me)))))
>>> 
>>> Nope, that's not thread safe either.
>> 
>> Well, first I did say so at the top, and second
>> I posted a second version which I beleive is
>> thread and condition safe.
>> 
>>> You're not rebinding, you're just assigning to the existing binding.  
>>> The only way to do this correctly is to redefine the function so that 
>>> it funcalls a function stored in the value cell of a special variable 
>>> and then rebind that special.
>> 
>> This is a bit confusing. What would be the _observable difference_
>> between what you suggest and what I have been proposing?
>> --
>> JFB
> 
> If you have a context switch at the position indicated then the thread 
> you switch to will see the "rebound" value.

Not in the version I posted about 10 minutes after the
one you are quoting (and about 4 hours before your reply):

> (defun test3 ()
>   (s-sysdeps:with-process-lock (*rebind-lock*)

Here context switches are blocked

>     (let ((old (symbol-function 'rebind-me)))
>       (unwind-protect
>           (progn
>             (rebind-me)
>             (setf (symbol-function 'rebind-me) (lambda () (format t 
> "rebound!~%")))
>             (rebind-me))

Here conditions are caught

>         (progn
>           (setf (symbol-function 'rebind-me) old)
>           (rebind-me))))))

Both of which are resumed at the end.

> You are making a very common mistake, not understanding the difference 
> between rebinding and reassignment.  Read 
> http://www.flownet.com/ron/specials.pdf.

I don't think so. The very same binding (symbol-function 'rebind-me)
is assigned ("setf'd") twice, The first time it is, any single call
to (rebind-me) will have to retreive whatever value is stored in
rebind-me's symbol-dunction slot, hence executing the lanbda.

The second time this very same binding is reassigned, the old
value is restored, thus "cleaming-up" and reverting (rebind-me)
to its original semantics.

I may have missed something very fundamental, in which case
I would be much obliged if my _precise_ mistake was pointed
out.

Many Thanks
--
JFBF
From: Ron Garret
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <rNOSPAMon-44D052.09480921012006@news.gha.chartermi.net>
In article <·························@news.aaisp.net.uk>,
 verec <·····@mac.com> wrote:

> > If you have a context switch at the position indicated then the thread 
> > you switch to will see the "rebound" value.
> 
> Not in the version I posted about 10 minutes after the
> one you are quoting (and about 4 hours before your reply):

Yes, even in that version.  (Also, you need to keep in mind that nntp is 
not a real-time protocol.)

> > (defun test3 ()
> >   (s-sysdeps:with-process-lock (*rebind-lock*)
> 
> Here context switches are blocked

No, they are not.

> > You are making a very common mistake, not understanding the difference 
> > between rebinding and reassignment.  Read 
> > http://www.flownet.com/ron/specials.pdf.
> 
> I don't think so.

I know you don't, but you are wrong.

> I may have missed something very fundamental,

You have.

> in which case
> I would be much obliged if my _precise_ mistake was pointed
> out.

It already has been: you do not understand the difference between 
rebinding and reassignment.  (There's a lot of other stuff you don't 
seem to understand as well, like how to block context switches, and why 
it's generally a bad idea to do so, but one thing at a time.)

Now go do your homework.

rg
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d28964$0$87294$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 17:48:49 +0000, Ron Garret <·········@flownet.com> said:

Ron, this is getting ridiculous.

I asked:

>>> What would be the _observable difference_
>>> between what you suggest and what I have been proposing?

You skipped over.

Then I asked:

>> I would be much obliged if my _precise_ mistake was pointed
>> out.

And again the only thing you have to say is:

> Now go do your homework.

So to make it clear:

> It already has been: you do not understand the difference between 
> rebinding and reassignment.

You are wrong BECAUSE you want to solve the problem in
terms of the question "How do I rebind" but NOT in the
term of its INTENT: How do I dynamically change the
behavior of a function at runtime.

Rebinding IS NOT NEEDED is this example. REASSIGNMENT is.

Please prove me wrong on this very point, and then, once I
see the light I may finally understand.

But please no generalities like:

> (There's a lot of other stuff you don't seem to understand as well, 
> like how to block context switches, and why it's generally a bad idea 
> to do so, but one thing at a time.)

True or not, they are unhelpful without appropriate context.

Thanks.
--
JFB
From: Ron Garret
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <rNOSPAMon-88C8E3.12071121012006@news.gha.chartermi.net>
In article <·························@news.aaisp.net.uk>,
 verec <·····@mac.com> wrote:

> On 2006-01-21 17:48:49 +0000, Ron Garret <·········@flownet.com> said:
> 
> Ron, this is getting ridiculous.

Indeed.

> I asked:
> 
> >>> What would be the _observable difference_
> >>> between what you suggest and what I have been proposing?
> 
> You skipped over.

No, I explained it to you.  You just didn't believe my answer.  Marcin 
Kowalczyk also posted an answer.  You apparently don't believe him 
either.

> Then I asked:
> 
> >> I would be much obliged if my _precise_ mistake was pointed
> >> out.
> 
> And again the only thing you have to say is:
> 
> > Now go do your homework.

No, that is not the only thing I had to say.  In fact, you cite the 
answer to your question in the very next passage:

> So to make it clear:
> 
> > It already has been: you do not understand the difference between 
> > rebinding and reassignment.
> 
> You are wrong BECAUSE you want to solve the problem in
> terms of the question "How do I rebind" but NOT in the
> term of its INTENT: How do I dynamically change the
> behavior of a function at runtime.
> 
> Rebinding IS NOT NEEDED is this example. REASSIGNMENT is.

Only if you don't have threads (or if you disable them, which is 
tantamount to the same thing, and which your code does not do).

> Please prove me wrong on this very point, and then, once I
> see the light I may finally understand.

You seem to be a little unclear about who is doing whom a favor here.

rg
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d297ad$0$87294$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 20:07:11 +0000, Ron Garret <·········@flownet.com> said:

> You seem to be a little unclear about who is doing whom a favor here.

Let's call it quit, Ron. OK?
--
JFB
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <87vewdabhk.fsf@qrnik.zagroda>
verec <·····@mac.com> writes:

>> (defun test3 ()
>>   (s-sysdeps:with-process-lock (*rebind-lock*)
>
> Here context switches are blocked

They are not. Only other calls to test3 are blocked.

And even if they were blocked, this would be a bad idea if the body
would take a long time.

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d2868f$0$87294$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 14:42:31 +0000, Marcin 'Qrczak' Kowalczyk 
<······@knm.org.pl> said:

> verec <·····@mac.com> writes:
> 
>>> (defun test3 ()
>>> (s-sysdeps:with-process-lock (*rebind-lock*)
>> 
>> Here context switches are blocked
> 
> They are not. Only other calls to test3 are blocked.

Good point.

But the assumption is that the rest of the program
cooperates.

BTW: I'm always amazed by the kind of reactions I see
often times in this forum.

There's a question:

     How do I get dynamic binding for functions ?

I rephrased it differently because the example given by the
OP suggested that what he wanted to do was to dynamically
"patch" a function, the way we would do it in C with a
function pointer.

But then, it so happens that each and evevy symbol is both
a value pointer and a function pointer, and that symbols
defined with defun have the same kind of dynamic extent as
symbols defined with defvar: in short globally accessible
from everywhere (package access not withstanding)

So it seems natural to reuse that symbol "as a pointer"
amd dynamically adjust what it is pointing to.

That's the gist of a very simple idea that solves the problem.

But then, I get nit-picked about threads and conditions and
what-not.

You know what: that's missing the point entirely. Sure
threading and conditions are valid issues, but so is the
fact that wou won't run out of memory, or disk space, and
that your ISP just didn't disconect you...

Because an as valid point as the one in your comment is:

"Beware, if the power goes down, you're toast!"

How true! And how irrelevant...
--
JFB
From: Coby Beck
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <DcwAf.88842$m05.5708@clgrps12>
"verec" <·····@mac.com> wrote in message 
······························@news.aaisp.net.uk...
> On 2006-01-21 14:42:31 +0000, Marcin 'Qrczak' Kowalczyk 
> <······@knm.org.pl> said:
>
>> verec <·····@mac.com> writes:
>>
>
> BTW: I'm always amazed by the kind of reactions I see
> often times in this forum.
>
> There's a question:
>
>     How do I get dynamic binding for functions ?
>
> I rephrased it differently because the example given by the
> OP suggested that what he wanted to do was to dynamically
> "patch" a function, the way we would do it in C with a
> function pointer.
>
> But then, it so happens that each and evevy symbol is both
> a value pointer and a function pointer, and that symbols
> defined with defun have the same kind of dynamic extent as
> symbols defined with defvar: in short globally accessible
> from everywhere (package access not withstanding)
>
> So it seems natural to reuse that symbol "as a pointer"
> amd dynamically adjust what it is pointing to.
>
> That's the gist of a very simple idea that solves the problem.
>
> But then, I get nit-picked about threads and conditions and
> what-not.

This is exactly the right reaction.  As the application programmer, one can 
decide if this is an important enough consideration to design for or not, 
but being unaware of it is a bad situation that "nit-pickers" can help you 
avoid.

> You know what: that's missing the point entirely. Sure
> threading and conditions are valid issues, but so is the
> fact that wou won't run out of memory, or disk space, and
> that your ISP just didn't disconect you...
>
> Because an as valid point as the one in your comment is:
>
> "Beware, if the power goes down, you're toast!"
>
> How true! And how irrelevant...

You are wrong here in a very deep way.  Now you may say "what can I do about 
someone tripping on the power cord?" and you can't do anything.  But there 
exists *many* situations where you can prevent serious losses in such an 
event by coding intelligently.  Again, you have the right to pick your 
battles but if you are unaware of your enemies, eventually you will suffer a 
big loss.

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d29667$0$87294$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 19:46:43 +0000, "Coby Beck" <·····@mercury.bc.ca> said:

>> You know what: that's missing the point entirely. Sure
>> threading and conditions are valid issues, but so is the
>> fact that wou won't run out of memory, or disk space, and
>> that your ISP just didn't disconect you...
>> 
>> Because an as valid point as the one in your comment is:
>> 
>> "Beware, if the power goes down, you're toast!"
>> 
>> How true! And how irrelevant...
> 
> You are wrong here in a very deep way.  Now you may say "what can I do 
> about someone tripping on the power cord?" and you can't do anything.  
> But there exists *many* situations where you can prevent serious losses 
> in such an event by coding intelligently.  Again, you have the right to 
> pick your battles but if you are unaware of your enemies, eventually 
> you will suffer a big loss.

You are right (that I am wrong) if you think I want to ignore the
details just by wishfull thinking that none of them will ever happen
to me or my programs.

But that is not what I intended to say. My point was about abstraction,
which, of necessity, discards the details, to come up to some
general line of understanding. Once you get there, you can flesh
it back with as many details you might want to decorate it with.

But you've got first to reach for the main idea, before trying
any of the dependents.

>> But then, I get nit-picked about threads and conditions and
>> what-not.
> 
> This is exactly the right reaction.

Not exactly. That is the right reaction when you implement.
But at design/imagination time, you want to get the nay-sayers
(the little details) out of the way. Otherwise they only
convince you to drop it all: "forget it, that's not possible!"

You may be interested in De Bono's book.
--
JFB
From: Coby Beck
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <DGxAf.89059$m05.44473@clgrps12>
"verec" <·····@mac.com> wrote in message 
······························@news.aaisp.net.uk...
> On 2006-01-21 19:46:43 +0000, "Coby Beck" <·····@mercury.bc.ca> said:
>>> But then, I get nit-picked about threads and conditions and
>>> what-not.
>>
>> This is exactly the right reaction.
>
> Not exactly. That is the right reaction when you implement.
> But at design/imagination time, you want to get the nay-sayers
> (the little details) out of the way. Otherwise they only
> convince you to drop it all: "forget it, that's not possible!"

And just when exactly would you rather learn that what you want to do is 
impossible?  At design time or after weeks, months and even years of 
development?  When do you want to learn that it is possible but very hard? 
If you are coding Lisp just for fun and enlightenment I suppose it doesn't 
matter but plenty of people have practical constraints.  Besides, these nits 
inevitably cross language barriers if they exist in Lisp.

This is the ideal exchange:

- How can I do X?
- This solution Y will do what you are asking, but there exist these nits: 
A B C.  A can be handled this way: Y1, A and B this way Y2.  C is not 
possible to prevent.
- Thanks, Y or Y1 is all I need. OR - Ok, this is harder than I thought but 
I'll do Y2 OR - But I really needed C handled, I had better rethink my 
application.

This forum is *very* good when these kinds of things come up.  Usually 
someone either quickly or naively provides solution Y, and others jump in 
with the nits and a cooperative effort implements Y1 and Y2 and the 
discussions of problem C are very illuminating.

The normal way this dynamic goes wrong is when the person who presented 
solution Y feels a need to defend it.  I have provided plenty of Y solutions 
over the years, sometimes because chances are it really is good enough and 
it is easy to provide,  sometimes because I forgot A B or C, sometimes 
because I was blissfully unaware of A B or C.  As far as I am concerned, no 
one mentioning the nits is worse than the blissful ignorance that otherwise 
results.

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d2bc0c$0$87296$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 21:26:59 +0000, "Coby Beck" <·····@mercury.bc.ca> said:

>>> This is exactly the right reaction.
>> 
>> Not exactly. That is the right reaction when you implement.
>> But at design/imagination time, you want to get the nay-sayers
>> (the little details) out of the way. Otherwise they only
>> convince you to drop it all: "forget it, that's not possible!"
> 
> And just when exactly would you rather learn that what you want to do 
> is impossible?  At design time or after weeks, months and even years of 
> development?  When do you want to learn that it is possible but very 
> hard? If you are coding Lisp just for fun and enlightenment I suppose 
> it doesn't matter but plenty of people have practical constraints.  
> Besides, these nits inevitably cross language barriers if they exist in 
> Lisp.

I cannot disagree.

> This is the ideal exchange:
> 
> - How can I do X?
> - This solution Y will do what you are asking, but there exist these 
> nits: A B C.  A can be handled this way: Y1, A and B this way Y2.  C is 
> not possible to prevent.
> - Thanks, Y or Y1 is all I need. OR - Ok, this is harder than I thought 
> but I'll do Y2 OR - But I really needed C handled, I had better rethink 
> my application.

I'm wrapping my head around Thomas solution to try and
understand how his solution is different/solves the threading
issue.

So far, my understanding of his code is that the magic happens
with the use of progv of which the CLHS says

    progv creates new dynamic variable bindings and executes
    each form using those bindings.

I've still to get a feel for the true significance of this.

> This forum is *very* good when these kinds of things come up.  Usually 
> someone either quickly or naively provides solution Y, and others jump 
> in with the nits and a cooperative effort implements Y1 and Y2 and the 
> discussions of problem C are very illuminating.
> 
> The normal way this dynamic goes wrong is when the person who presented 
> solution Y feels a need to defend it.

(Shame on me )-:

But on the other hand, and assuming that ``progv'' is the magic
ingredient, why is it that so many posts just dismiss your Y solution
by showing you all those A, B and C's, yet fail to provide even
a hint as to where to start?

My rule is: either I have a solution (possibly a Y) and I show
it, or I don't and I just shut up.

At the very least, when someone answers with an A/B/C I would
expect a detailed analysis of:
1. why A shows up
2. why it is imnportant to solve A
3. what the consequences would be of not solving it.

Throwing a pointer to the basics of binding is not the solution.

Showing that ``progv'' might solve the problem is, on the contrary,
very good.

Burrying the ``progv'' inside a macro without further hint is a bit
teasing ... but far better than the alternatives :-)

> I have provided plenty of Y solutions over the years, sometimes because 
> chances are it really is good enough and it is easy to provide,  
> sometimes because I forgot A B or C, sometimes because I was blissfully 
> unaware of A B or C.  As far as I am concerned, no one mentioning the 
> nits is worse than the blissful ignorance that otherwise results.

See above. Mentionning the nits without offering a solution is just
fruitless, unless you mention the whole rationale.

It's so easy to throw rocks, and yet, so difficult to actually come
up with a (Y+1) that sticks, that I can understand why people do it,
but that's no excuse.
--
JFB
From: Rob Warnock
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <pfSdnTD5Xo-uZk_eRVn-vw@speakeasy.net>
verec  <·····@mac.com> wrote:
+---------------
| I'm wrapping my head around Thomas solution to try and understand
| how his solution is different/solves the threading issue.
| So far, my understanding of his code is that the magic happens
| with the use of progv ...
+---------------

Not really; PROGV per se is a red herring. It has nothing to do
with the core issue, which is this: Even though the CLHS says 
nothing about "threading", the Common Lisp community -- and 
especially the community of implementors (competitors though 
they might be!) -- have generally come to a consensus of how 
dynamic variables should behave in the presence of threading 
[any kind of threading -- green, "native", POSIX, etc], which 
is roughly the following [apologies if I don't use exactly the 
proper terminology]:

In the absence of threading [or with only one thread active], 
things behave exactly as in CLHS 3.1.2.1.1.2 "Dynamic Variables":

    At any given time, all dynamic variables with a given name refer
    to exactly one binding, either in the dynamic environment or in
    the global environment.

where "the global environment", sometimes called the top-level
environment, is simply whatever contains the binding for a special
variable when it is not dynamically bound. Any assignment [with
SETF/SETQ or things that expand to them such as INCF or PUSH] affects 
only the single, current dynamic binding. During the dynamic extent 
of a LET- or LAMBDA-binding, there is no way to change the original 
"global" value or any of the values saved on the "stack" of dynamic 
bindings. Also, (SETF (SYMBOL-VALUE sym) ...) is required to act on 
the current dynamic binding. See the CLHS for many other gory details.

*With* threading, the model changes only slightly, but *VERY* 
significantly, as follows:

1. All of the threads that have *not* LET- or LAMBDA-bound a special
   variable continue to share a single view of a global or top-level
   value. Any assignment (SETF) to that variable is seen by all threads 
   which have *not* LET- or LAMBDA-bound that special variable.

2. Any thread which *does* LET- or LAMBDA-bind a special variable
   creates a *new* conceptual variable and related "stack" of dynamic 
   bindings which is private to that thread [and in some (most?) 
   implementations, its descendents, assuming they don't further bind
   it themselves]. Assignments to or further dynamic rebindings of
   the variable within that thread are seen *only* by that thread [and
   descendents], *NOT* by any of the other threads [which see either
   the top-level binding or their own, private LET- or LAMBDA-bindings].

Thus, threading replaces the CLHS notion that a special variable
always has a *single* binding [which can be dynamically bound in
a *single* conceptual "stack"] with the concept that the first
LET- or LAMBDA-binding of a given special variable by a given
thread creates a *new* per-thread binding [and associated conceptual
"stack" of further dynamic bindings].

So how does this apply to your question about "dynamic functions"? 
Well, since the above "threading model of dynamic variables" is by  
now so firmly established in the CL community as "the right way", 
there is a natural expectation that any implementation of "dynamic 
functions" would behave EXACTLY THE SAME WAY with respect to threading. 
That is, that any DFLET form executed within a thread would create 
a new function binding that would be seen ONLY WITHIN THAT THREAD
(and descendants), just as the above model does for special variables.

And *that* is why various people have been *strongly* suggesting
that you make your dynamic function facility store the current
binding in a per-function-name special variable and use FUNCALL
(or APPLY) indirection through the special variable -- because,
if you do that, the "expected" (by the community) behavior for
things dynamic in the presence of threads will "just happen"
automatically in any implementation that follows the consensus
model of threading and special variables. And if you *don't*
do that, then it won't.

Capische?


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d30f63$0$87291$5a6aecb4@news.aaisp.net.uk>
On 2006-01-22 03:25:39 +0000, ····@rpw3.org (Rob Warnock) said:

> verec  <·····@mac.com> wrote:
> +---------------
> | I'm wrapping my head around Thomas solution to try and understand
> | how his solution is different/solves the threading issue.
> | So far, my understanding of his code is that the magic happens
> | with the use of progv ...
> +---------------
> 
> Not really; PROGV per se is a red herring. It has nothing to do
> with the core issue, which is this: Even though the CLHS says nothing 
> about "threading", the Common Lisp community -- and especially the 
> community of implementors (competitors though they might be!) -- have 
> generally come to a consensus of how dynamic variables should behave in 
> the presence of threading [any kind of threading -- green, "native", 
> POSIX, etc], which is roughly the following [apologies if I don't use 
> exactly the proper terminology]:
> 
> In the absence of threading [or with only one thread active], things 
> behave exactly as in CLHS 3.1.2.1.1.2 "Dynamic Variables":
> 
>     At any given time, all dynamic variables with a given name refer
>     to exactly one binding, either in the dynamic environment or in
>     the global environment.
> 
> where "the global environment", sometimes called the top-level
> environment, is simply whatever contains the binding for a special
> variable when it is not dynamically bound. Any assignment [with
> SETF/SETQ or things that expand to them such as INCF or PUSH] affects 
> only the single, current dynamic binding. During the dynamic extent of 
> a LET- or LAMBDA-binding, there is no way to change the original 
> "global" value or any of the values saved on the "stack" of dynamic 
> bindings. Also, (SETF (SYMBOL-VALUE sym) ...) is required to act on the 
> current dynamic binding. See the CLHS for many other gory details.
> 
> *With* threading, the model changes only slightly, but *VERY* 
> significantly, as follows:
> 
> 1. All of the threads that have *not* LET- or LAMBDA-bound a special
>    variable continue to share a single view of a global or top-level
>    value. Any assignment (SETF) to that variable is seen by all threads 
>    which have *not* LET- or LAMBDA-bound that special variable.
> 
> 2. Any thread which *does* LET- or LAMBDA-bind a special variable
>    creates a *new* conceptual variable and related "stack" of dynamic   
>  bindings which is private to that thread [and in some (most?)    
> implementations, its descendents, assuming they don't further bind
>    it themselves]. Assignments to or further dynamic rebindings of
>    the variable within that thread are seen *only* by that thread [and
>    descendents], *NOT* by any of the other threads [which see either
>    the top-level binding or their own, private LET- or LAMBDA-bindings].
> 
> Thus, threading replaces the CLHS notion that a special variable
> always has a *single* binding [which can be dynamically bound in
> a *single* conceptual "stack"] with the concept that the first
> LET- or LAMBDA-binding of a given special variable by a given
> thread creates a *new* per-thread binding [and associated conceptual
> "stack" of further dynamic bindings].
> 
> So how does this apply to your question about "dynamic functions"? 
> Well, since the above "threading model of dynamic variables" is by  now 
> so firmly established in the CL community as "the right way", there is 
> a natural expectation that any implementation of "dynamic functions" 
> would behave EXACTLY THE SAME WAY with respect to threading. That is, 
> that any DFLET form executed within a thread would create a new 
> function binding that would be seen ONLY WITHIN THAT THREAD
> (and descendants), just as the above model does for special variables.
> 
> And *that* is why various people have been *strongly* suggesting
> that you make your dynamic function facility store the current
> binding in a per-function-name special variable and use FUNCALL
> (or APPLY) indirection through the special variable -- because,
> if you do that, the "expected" (by the community) behavior for
> things dynamic in the presence of threads will "just happen"
> automatically in any implementation that follows the consensus
> model of threading and special variables. And if you *don't*
> do that, then it won't.
> 
> Capische?

Except for the very last word (Italian?), I think I get it.
Many thanks
--
JFB
From: Rob Warnock
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <9uKdnb4o-I18iE7eRVn-hg@speakeasy.net>
verec  <·····@mac.com> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) said:
| > Capische?
| 
| Except for the very last word (Italian?), I think I get it. Many thanks
+---------------

"Capische?", also spelled "capiche?" or "capisce?" or "capisci?",
simply means "[Do you] understand?", or more colloquially, "Got it?"  ;-}

And you're more than welcome. Glad to have helped.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d33a34$0$87296$5a6aecb4@news.aaisp.net.uk>
On 2006-01-22 05:19:29 +0000, ····@rpw3.org (Rob Warnock) said:

> "Capische?", also spelled "capiche?" or "capisce?" or "capisci?",
> simply means "[Do you] understand?", or more colloquially, "Got it?"  ;-}
> 
> And you're more than welcome. Glad to have helped.

Compris!

Merci beaucoup :-)
--
JFB
From: John Thingstad
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <op.s3q818e0pqzri1@mjolner.upc.no>
On Sat, 21 Jan 2006 23:56:08 +0100, verec <·····@mac.com> wrote:


> I'm wrapping my head around Thomas solution to try and
> understand how his solution is different/solves the threading
> issue.
>
> So far, my understanding of his code is that the magic happens
> with the use of progv of which the CLHS says
>
>     progv creates new dynamic variable bindings and executes
>     each form using those bindings.
>
> I've still to get a feel for the true significance of this.
>

(defun f() (declare (special x)) (format nil "~A" x))

CL-USER 14 > (progv '(x) '(2) (f))
"2"
CL-USER 15 > (let ((x 2)) (f))

Error: The variable X is unbound.

As you see a dynamic value is seen by all functions called in it's scope.
A lexical variable is only visible to operations in that scope.

Global variables are dynamic.
When you create a new thread it creates a new global vaiabes set.
Well actually it dosn't. It uses lazy evaluation and copies on demand when  
the
value is changed, but it should behave as though it does.

If you have powerpoint you can view Roger Cormans presentation on the  
implementation
on OS MuliThreading in Corman Lisp.
http://www.google.com/search?hl=en&hs=dZn&client=opera&rls=en&q=Roger+Corman.+MultiThreaded+Lisp&spell=1

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d2ed37$0$87294$5a6aecb4@news.aaisp.net.uk>
On 2006-01-22 00:59:58 +0000, "John Thingstad" <··············@chello.no> said:

> (defun f() (declare (special x)) (format nil "~A" x))
> 
> CL-USER 14 > (progv '(x) '(2) (f))
> "2"
> CL-USER 15 > (let ((x 2)) (f))
> 
> Error: The variable X is unbound.
> 
> As you see a dynamic value is seen by all functions called in it's scope.
> A lexical variable is only visible to operations in that scope.
> 
> Global variables are dynamic.
> When you create a new thread it creates a new global vaiabes set.
> Well actually it dosn't. It uses lazy evaluation and copies on demand when  the
> value is changed, but it should behave as though it does.
> 
> If you have powerpoint you can view Roger Cormans presentation on the  
> implementation
> on OS MuliThreading in Corman Lisp.
> http://www.google.com/search?hl=en&hs=dZn&client=opera&rls=en&q=Roger+Corman.+MultiThreaded+Lisp&spell=1

Many 
> 
thanks John.

The 9nth link from the top of the page your Google link points
to is a reference to a paper by Pascal Constanza:

http://p-cos.net/documents/special-full.pdf

which contains a much illuminating presentation of progv
plus other constructs.

Many thanks
--
JFB
From: Coby Beck
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <HoCAf.89600$m05.27943@clgrps12>
"verec" <·····@mac.com> wrote in message 
······························@news.aaisp.net.uk...
> On 2006-01-21 21:26:59 +0000, "Coby Beck" <·····@mercury.bc.ca> said:
>
> My rule is: either I have a solution (possibly a Y) and I show
> it, or I don't and I just shut up.
>
> At the very least, when someone answers with an A/B/C I would
> expect a detailed analysis of:
> 1. why A shows up
> 2. why it is imnportant to solve A
> 3. what the consequences would be of not solving it.

This is a tall order considering no one is paid or otherwise obligated to 
put in that kind of effort.  We are fortunate that in c.l.l. there are 
actually people who will do just that from time to time but if the 
occasional post goes by without such depth of response it's hardly fair to 
be upset about it.

>> I have provided plenty of Y solutions over the years, sometimes because 
>> chances are it really is good enough and it is easy to provide, 
>> sometimes because I forgot A B or C, sometimes because I was blissfully 
>> unaware of A B or C.  As far as I am concerned, no one mentioning the 
>> nits is worse than the blissful ignorance that otherwise results.
>
> See above. Mentionning the nits without offering a solution is just
> fruitless, unless you mention the whole rationale.

No, it is just a way of sharing the work load.  The OP is the only one who 
should feel obligated, but usually someone else will expand a bit, and 
someone else a bit more etc.  Follow up questions are rarely ignored, 
especially if they show a bit of additional thought or focus.

> It's so easy to throw rocks, and yet, so difficult to actually come
> up with a (Y+1) that sticks, that I can understand why people do it,
> but that's no excuse.

It is easy to throw rocks at someone else's code.  But sometimes, if you 
pick one up, bloody from hitting you in the head, you will find it is a 
pearl.  I would also note that some one really trying their best might be 
thinking that what they are pointing out is just a "brain fart" type of 
oversight and a lengthy explanation would be taken as patronizing!  It is so 
hard to really know what someone on the other side of your screen is 
actually thinking or feeling, just remember that and *always* assume the 
best.  Oh yeah, rule number two, when you finally have proof of the worst, 
just stop replying.

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Stefan Kamphausen
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <1138008375.403151.284980@g44g2000cwa.googlegroups.com>
Hi,

sorry for being late to the discussion ... 'twas weekend :-)

First of all:  Thanks for the easy solutions.  I thought about a
funcall and a defvar, too, but that would be rewriting lots of code.

Nevertheless, the discussion following gave me a lot of insights and
thus was of value to me (being the OP).  So again: thanks.

Speaking in terms of the last post:

>- How can I do X?

This is what I asked

> - This solution Y will do what you are asking, but there exist these nits:

This is what I got

> A B C.  A can be handled this way: Y1, A and B this way Y2.  C is not
> possible to prevent.

This gave me insight and might be a relevant discussion to others, more
involved in the actual development of lisps.

> - Thanks, Y or Y1 is all I need. OR - Ok, this is harder than I thought but
> I'll do Y2 OR - But I really needed C handled, I had better rethink my
> application.

Thanks, I don't need to be thread aware in this situation (me
developing with CL for less than a year now).  Ok, this is harder than
I thought and of course I had better rethink my application ;-)

Regards,
Stefan
From: Pascal Bourguignon
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <873bjhfifh.fsf@thalassa.informatimago.com>
"Coby Beck" <·····@mercury.bc.ca> writes:
>> How true! And how irrelevant...
>
> You are wrong here in a very deep way.  Now you may say "what can I do about 
> someone tripping on the power cord?" and you can't do anything.  But there 
> exists *many* situations where you can prevent serious losses in such an 
> event by coding intelligently.  Again, you have the right to pick your 
> battles but if you are unaware of your enemies, eventually you will suffer a 
> big loss.

And actually, programmers can do a lot to avoid problems when someone
trips on the power cord.  Like develop a journalized file system, etc.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

This is a signature virus.  Add me to your signature and help me to live.
From: Pascal Bourguignon
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <87acdpfk4r.fsf@thalassa.informatimago.com>
verec <·····@mac.com> writes:
> That's the gist of a very simple idea that solves the problem.
>
> But then, I get nit-picked about threads and conditions and
> what-not.

But this attention to details makes Lisp a better programming language
than the others.

Also, if we cannot come with a solution satisfying these points, that
means that fdlet would need to be a special operator, that is, it may
be a way to explore to extend (and improve) Common Lisp.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

What is this talk of 'release'? Klingons do not make software 'releases'.
Our software 'escapes' leaving a bloody trail of designers and quality
assurance people in it's wake.
From: Kenny Tilton
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <nZxAf.4696$cj3.3876@news-wrt-01.rdc-nyc.rr.com>
verec wrote:
> On 2006-01-21 14:42:31 +0000, Marcin 'Qrczak' Kowalczyk 
> <······@knm.org.pl> said:
> 
>> verec <·····@mac.com> writes:
>>
>>>> (defun test3 ()
>>>> (s-sysdeps:with-process-lock (*rebind-lock*)
>>>
>>>
>>> Here context switches are blocked
>>
>>
>> They are not. Only other calls to test3 are blocked.
> 
> 
> Good point.
> 
> But the assumption is that the rest of the program
> cooperates.
> 
> BTW: I'm always amazed by the kind of reactions I see
> often times in this forum.

That comment will help.

Yeah, what is wrong with /all/ of us? I saw you holding forth on 
emotional IQ elsewhere. I never heard of that one. Social IQ I have 
heard about. :)

> 
> There's a question:
> 
>     How do I get dynamic binding for functions ?
> 
> I rephrased it differently because the example given by the
> OP suggested that what he wanted to do was to dynamically
> "patch" a function, the way we would do it in C with a
> function pointer.
> 
> But then, it so happens that each and evevy symbol is both
> a value pointer and a function pointer, and that symbols
> defined with defun have the same kind of dynamic extent as
> symbols defined with defvar: in short globally accessible
> from everywhere (package access not withstanding)
> 
> So it seems natural to reuse that symbol "as a pointer"
> amd dynamically adjust what it is pointing to.
> 
> That's the gist of a very simple idea that solves the problem.
> 
> But then, I get nit-picked about threads and conditions and
> what-not.
> 
> You know what: that's missing the point entirely. Sure
> threading and conditions are valid issues, but so is the
> fact that wou won't run out of memory, or disk space, and
> that your ISP just didn't disconect you...

There is a line, and you crossed it. A language extension being 
incompatible with the extended language is not the same as a power 
failure. It's no good thinking big and ignoring the so-called details if 
in the end those tiny little details will leave you announcing your 
super-duper dynamic function package that  "works with most of Lisp".

We are fortunate to have some top CL talents in this NG (not me, I just 
do apps) and you can absolutely count on learning a ton no matter what 
you say here.

That is a feature, not a bug.

kenny
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d2c357$0$87296$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 21:46:59 +0000, Kenny Tilton <·············@nyc.rr.com> said:

>> BTW: I'm always amazed by the kind of reactions I see
>> often times in this forum.
> 
> That comment will help.
> 
> Yeah, what is wrong with /all/ of us?

Ah ... generalization ... "often-times" => /all/ ???

> I saw you holding forth on emotional IQ elsewhere. I never
> heard of that one. Social IQ I have heard about. :)

Never too late :-)

> There is a line, and you crossed it. A language extension being 
> incompatible with the extended language is not the same as a power 
> failure.

AFAIK, threading is *not* part of ANSI CL (nor the HyperSpec) even
though most implementations provide one form or another. I just learnt
via Marcin post that:

> 4. The consensus of Common Lisp threading systems is that newly
>    created threads use global bindings of dynamic variables instead of
>    inheriting bindings from the place of creation of the new thread.

So, nit-picking on non-standard features, at a time when it is still
the case that the vast majority of existing programs are still mono
threaded, and throwing As, Bs or Cs at "my" Y which otherwise works
pretty well in mono-threaded implementations is, at best, unfair.

As I said in reply to Coby, if anyone had, (as Thomas has done),
pointed out that ``progv'' would solve the problem whether the
implementation was multi-threaded or not, or had provided the context
that Marcin gave (and that I just quoted above), then there would have
been no room for me to start whining.

> It's no good thinking big and ignoring the so-called details if in the 
> end those tiny little details will leave you announcing your 
> super-duper dynamic function package that  "works with most of Lisp".

Agreed.

> That is a feature, not a bug.

Hmmm. Sounds like a spec, to me :-)
--
JFB
From: Thomas F. Burdick
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <xcvwtgszjun.fsf@conquest.OCF.Berkeley.EDU>
verec <·····@mac.com> writes:

> As I said in reply to Coby, if anyone had, (as Thomas has done),
> pointed out that ``progv'' would solve the problem whether the
> implementation was multi-threaded or not, or had provided the context
> that Marcin gave (and that I just quoted above), then there would have
> been no room for me to start whining.

Hey don't pull me into this.  Your whining is your own doing, and if
you'd read the constructive criticisms of your code with a
non-jaundiced eye, you might have noticed that you *were* being
pointed in the right direction.  Instead you started rabidly defending
your ignorant newbie mistake as though that were a feature instead of
a shortcomming -- and spawned an annoyingly large flamy thread.  I was
merely trying to make sure the correct answer to this question was
noticed by the OP, since the helpful information was buried in the
middle of a stupid argument.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <877j8ts1vc.fsf@qrnik.zagroda>
verec <·····@mac.com> writes:

>>> Here context switches are blocked
>> They are not. Only other calls to test3 are blocked.
>
> Good point.
>
> But the assumption is that the rest of the program cooperates.

"Cooperation" would require to lock the same mutex around call code
which calls REBIND-ME. This is quite intrusive.

What is worse, the proper semantics is not to block other threads but
to let the rebinding be visible only in the given thread.

> But then, it so happens that each and evevy symbol is both
> a value pointer and a function pointer,

True.

> and that symbols defined with defun have the same kind of dynamic
> extent as symbols defined with defvar:

False: the value slot can be rebound locally, while the function slot
is only global.

> So it seems natural to reuse that symbol "as a pointer" amd
> dynamically adjust what it is pointing to.

LET doesn't work by temporarily replacing the current value:

1. The change is visible only in the given thread. Other threads are
   not blocked though, they see a different variable.

2. It's not the value which is being replaced but the mutable slot.
   When two threads haven't replaced it, they observe effects of each
   other's SETQ / SET on that variable. When one of them has replaced
   it, SETQ / SET in them operate on distinct slots.

> You know what: that's missing the point entirely. Sure threading and
> conditions are valid issues, but so is the fact that wou won't run
> out of memory, or disk space, and that your ISP just didn't disconect
> you...

You can't defend against these conditions on this level of abstraction,
but it is possible to implement dynamically bound functions correctly
wrt. threads. The function must be stored in the value slot of some
symbol, and the function slot is kept constant: being a function which
retrieves that value slot and calls the function found there.

                          *       *       *

There are several things I don't like about Lisp special variables:

1. The same syntax (LET) is used for creation of a new lexical
   variable and for rebinding an existing dynamic variable, even
   though they are quite different operations.

   While this enables a convenience that function parameters can
   directly rebind dynamic variables, it also has disadvantages:

2. Specialness is a property of the symbol instead of the variable.
   This is a consequence of 1.

   It could have been designed differently, such that a lexical
   variable can shadow a dynamic variable and vice versa. It would
   make unnecessary to distinguish dynamic variables by a naming
   convention.

3. Dynamic variables are only global. This is a consequence of 2.
   In principle dynamic variables could even be object fields.

4. The consensus of Common Lisp threading systems is that newly
   created threads use global bindings of dynamic variables instead of
   inheriting bindings from the place of creation of the new thread.

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: Joe Marshall
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <1137906123.488747.15870@g44g2000cwa.googlegroups.com>
Marcin 'Qrczak' Kowalczyk wrote:
>
> There are several things I don't like about Lisp special variables:
>
> 1. The same syntax (LET) is used for creation of a new lexical
>    variable and for rebinding an existing dynamic variable, even
>    though they are quite different operations.
>
>    While this enables a convenience that function parameters can
>    directly rebind dynamic variables, it also has disadvantages:
>
> 2. Specialness is a property of the symbol instead of the variable.
>    This is a consequence of 1.
>
>    It could have been designed differently, such that a lexical
>    variable can shadow a dynamic variable and vice versa. It would
>    make unnecessary to distinguish dynamic variables by a naming
>    convention.
>
> 3. Dynamic variables are only global. This is a consequence of 2.
>    In principle dynamic variables could even be object fields.

On the Lisp machine, object fields could be dynamic.

> 4. The consensus of Common Lisp threading systems is that newly
>    created threads use global bindings of dynamic variables instead of
>    inheriting bindings from the place of creation of the new thread.

This seems to be how most Common Lisp systems behave, but I don't think
it is reasonable.  It seems to me that the binding cell present at the
time the thread was forked should appear as `global' in the forked
thread by default.  This is trickier to implement, but I believe the
model would be easier to understand.
From: Rob Warnock
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <VYWdnY2PmagrnU7enZ2dnUVZ_tudnZ2d@speakeasy.net>
Marcin 'Qrczak' Kowalczyk  <······@knm.org.pl> wrote:
+---------------
| 4. The consensus of Common Lisp threading systems is that newly
|    created threads use global bindings of dynamic variables instead of
|    inheriting bindings from the place of creation of the new thread.
+---------------

Wow! One learns something new every day! I would have thought the
"natural" way would be to inherit the same thread-local variables,
but CMUCL seems to agree with you:

    > (defvar *x* 3)

    *X*
    u> (defun x () (format t "~&*X* = ~s~%" *X*))

    X
    > (x)
    *X* = 3
    NIL
    > (let ((*x* 17))
	(flet ((pfunc () (sleep 5) (x)))
	  (mp:make-process #'pfunc)))

    #<Process Anonymous {488E00BD}>
    >
    *X* = 3		<-- Printed asynchronously

Looking further at MAKE-PROCESS, I discovered that it provides a
separate explicit keyword argument to set any desired "extra"
special bindings for the new thread, which are indeed private
to the thread:

    > (let ((*x* 17))
	(flet ((pfunc () (sleep 5) (x)))
	  (mp:make-process #'pfunc :initial-bindings '((*x* . 29)))
	  (sleep 1)
	  (x)))

    *X* = 17
    NIL
    > (x)	; manually typed

    *X* = 3
    NIL
    > 
    *X* = 29		<-- Printed asynchronously

Do any of the old-timers have any history to share on why it was
chosen to work this way?


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Joe Marshall
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <1137908693.673744.57790@g14g2000cwa.googlegroups.com>
Rob Warnock wrote:
>
> Wow! One learns something new every day! I would have thought the
> "natural" way would be to inherit the same thread-local variables,
> but CMUCL seems to agree with you:
>
>
> Do any of the old-timers have any history to share on why it was
> chosen to work this way?

I'm still a youngster, but the reason is this:  Implementing special
variables through use of shallow binding is, in general, more efficient
than using deep binding if you are implementing threading by
time-division multiplexing.  When a thread is not currently active, the
value cells of the special bindings are saved along with the rest of
the thread state.  If the dynamic value cells were shared among
threads, there would be need for an `invisible forwarding pointer' in
the value cell of the symbol so different threads would continue to
share the value cells when they were swapped out.

Although the Lisp machine had these (external value cell pointers), it
was generally agreed amongst the stock hardware implementors that it
would be too expensive to check for fowarding pointers on every
symeval.

However, now that threading isn't always done by time-slice
multiplexing, there is no reason you *couldn't* have it work the way
you and I think it ought.  Both Franz Allegro and Lispworks have some
sort of hashing mechanism so that value cells are part of the `thread
local' storage.  As far as I know, there's no reason why these cells
couldn't initially be hashed to the same locations at the time the
thread starts, but it might break legacy code, which both Franz and
Lispworks are reluctant to do.
From: jayessay
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <m3psmkalda.fsf@rigel.goldenthreadtech.com>
····@rpw3.org (Rob Warnock) writes:

> Marcin 'Qrczak' Kowalczyk  <······@knm.org.pl> wrote:
> +---------------
> | 4. The consensus of Common Lisp threading systems is that newly
> |    created threads use global bindings of dynamic variables instead of
> |    inheriting bindings from the place of creation of the new thread.
> +---------------
...
> Do any of the old-timers have any history to share on why it was
> chosen to work this way?

There was a big "hoo-de-doo" (discussion) revolving around this point
a year or so ago.  I can't recall the thread title off hand...


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Thomas F. Burdick
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <xcv64oc1ux3.fsf@conquest.OCF.Berkeley.EDU>
····@rpw3.org (Rob Warnock) writes:

> Marcin 'Qrczak' Kowalczyk  <······@knm.org.pl> wrote:
> +---------------
> | 4. The consensus of Common Lisp threading systems is that newly
> |    created threads use global bindings of dynamic variables instead of
> |    inheriting bindings from the place of creation of the new thread.
> +---------------
> 
> Wow! One learns something new every day! I would have thought the
> "natural" way would be to inherit the same thread-local variables,
> but CMUCL seems to agree with you:

There are basically two ways to view what MAKE-PROCESS ought to do:
either it's a magical sort of parallel-funcall that creates a dynamic
closure; or it registers a function to be called at some point in a
new dynamic contour.  (You can probably guess which view I share by
the wording).

> Looking further at MAKE-PROCESS, I discovered that it provides a
> separate explicit keyword argument to set any desired "extra"
> special bindings for the new thread, which are indeed private
> to the thread:

Which is a really Common Lisp-y thing to do -- this just turns into a
PROGV in the newly created thread, but is very useful.

> Do any of the old-timers have any history to share on why it was
> chosen to work this way?

Not all implementations work this way.  SBCL's threads were not-quite
dynamic closures (ie, close to what you were intuitively expecting)
until 0.9.6.  I believe Corman's are as well.  If you want to see the
reasoning behind SBCL's switch, G�bor proposed the change to the
sbcl-devel list here:

  http://sourceforge.net/mailarchive/forum.php?thread_id=8537377&forum_id=4134

There were previous Lisp dialects (notably INTERLISP) where dynamic
closures were a normal thing to use.  The general, but not universal,
assesment seems to be that they were more confusing than they were
useful.  Then again, I don't know if that's the general consensus
among former-INTERLISPers.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Thomas F. Burdick
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <xcv1wz01ujw.fsf@conquest.OCF.Berkeley.EDU>
Marcin 'Qrczak' Kowalczyk <······@knm.org.pl> writes:

> There are several things I don't like about Lisp special variables:

Half of them seem to be misunderstandings:

> 1. The same syntax (LET) is used for creation of a new lexical
>    variable and for rebinding an existing dynamic variable, even
>    though they are quite different operations.
> 
>    While this enables a convenience that function parameters can
>    directly rebind dynamic variables, it also has disadvantages:
> 
> 2. Specialness is a property of the symbol instead of the variable.
>    This is a consequence of 1.

No, specialness is a property of the variable.

>    It could have been designed differently, such that a lexical
>    variable can shadow a dynamic variable and vice versa. It would
>    make unnecessary to distinguish dynamic variables by a naming
>    convention.

This is in fact exactly how things work.

> 3. Dynamic variables are only global. This is a consequence of 2.
>    In principle dynamic variables could even be object fields.

As a consequence of 2, this is wrong.  All global variables are
globally special, but that is a *very* different thing from what
you're asserting.

> 4. The consensus of Common Lisp threading systems is that newly
>    created threads use global bindings of dynamic variables instead of
>    inheriting bindings from the place of creation of the new thread.

It's not a consensus, but it is the most common decision.  Since
threads don't return back into their parent thread, I don't see how it
makes sense to think of the new thread as in the dynamic contour of
the parent thread.  It sounds to me like your real issue here is that
CL doesn't have continuations.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Ron Garret
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <rNOSPAMon-9B2556.09095822012006@news.gha.chartermi.net>
In article <···············@conquest.OCF.Berkeley.EDU>,
 ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) wrote:

> Marcin 'Qrczak' Kowalczyk <······@knm.org.pl> writes:
> 
> > There are several things I don't like about Lisp special variables:
> 
> Half of them seem to be misunderstandings:
> 
> > 1. The same syntax (LET) is used for creation of a new lexical
> >    variable and for rebinding an existing dynamic variable, even
> >    though they are quite different operations.
> > 
> >    While this enables a convenience that function parameters can
> >    directly rebind dynamic variables, it also has disadvantages:
> > 
> > 2. Specialness is a property of the symbol instead of the variable.
> >    This is a consequence of 1.
> 
> No, specialness is a property of the variable.

Actually, it can be both.

> >    It could have been designed differently, such that a lexical
> >    variable can shadow a dynamic variable and vice versa. It would
> >    make unnecessary to distinguish dynamic variables by a naming
> >    convention.
> 
> This is in fact exactly how things work.

Not necessarily.  Once a symbol has been globally declared special there 
is no way to shadow it with a lexical binding.

> > 3. Dynamic variables are only global. This is a consequence of 2.
> >    In principle dynamic variables could even be object fields.
> 
> As a consequence of 2, this is wrong.  All global variables are
> globally special, but that is a *very* different thing from what
> you're asserting.

No, it isn't very different.  "All global variables are globally 
special" is indistinguishable from "all variables associated with this 
symbol are special."

rg
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <871wz04dgd.fsf@qrnik.zagroda>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:

>> 2. Specialness is a property of the symbol instead of the variable.
>>    This is a consequence of 1.
>
> No, specialness is a property of the variable.

Ok, it can be either:

"When used in a proclamation, a special declaration specifier applies
to all bindings as well as to all references of the mentioned
variables."

In order to make a given symbol refer to a special variable in all
contexts where it's not shadowed, it must either be declared as
special in all those contexts individually, or all variables named
with the given symbol must be special, i.e. it becomes impossible
to shadow.

>>    It could have been designed differently, such that a lexical
>>    variable can shadow a dynamic variable and vice versa. It would
>>    make unnecessary to distinguish dynamic variables by a naming
>>    convention.
>
> This is in fact exactly how things work.

Not exactly. Here is how it works in my design:

   There are 3 fundamental operations related to lexical variables:
   creation, getting the current value, and setting the current value.

   There are 4 fundamental operations related to dynamic variables:
   creation, getting the current value, setting the current value,
   and establishes a new local binding in the given dynamic extent.

   ("Current value" of a dynamic variable really means "current value
   of the current binding".)

   Getting the current value of either type of variable uses the same
   syntax. Ditto for setting. But not for creation, because the type
   of the variable must be specified somehow, and obviously not for
   making a local binding, which is applicable only to dynamic
   variables.

   Creation happens in various contexts, corresponding to Common Lisp
   LET/DEFVAR, LAMBDA/DEFUN, slots etc. In each case you can choose
   the type of the variable.

   Creation always shadows any outer meaning of the symbol. Making
   a local binding applies to an existing variable and doesn't shadow
   anything, doesn't affect the static environment at all.

CL conflates creation of a lexical variable with making a local
binding of a dynamic variable. It distinguishes them with declarations.

In my design a naming convention for special variables is not essential
because you can't accidentally change a special variable when creation
of a new lexical variable was intended. At the same time you don't have
to declare a given symbol as special in all functions where it's used.

Actually most of this design exists in CL, accessible behind a level
of indirection: GENSYM, SYMBOL-VALUE, SET, and PROGV. Here the dynamic
variable is accessed e.g. through an auxiliary lexical variable, and
thus getting and setting the value looks differently than for ordinary
lexical and ordinary dynamic variables.

>> 3. Dynamic variables are only global. This is a consequence of 2.
>>    In principle dynamic variables could even be object fields.
>
> As a consequence of 2, this is wrong.  All global variables are
> globally special, but that is a *very* different thing from what
> you're asserting.

I didn't mean that.

I meant that there exists only one dynamic variable per symbol, while
there can be many lexical variables per symbol.

It's true that symbols don't have to be global; this requires an
indirection when using the variable.

>> 4. The consensus of Common Lisp threading systems is that newly
>>    created threads use global bindings of dynamic variables instead of
>>    inheriting bindings from the place of creation of the new thread.
>
> It's not a consensus, but it is the most common decision. Since
> threads don't return back into their parent thread, I don't see how
> it makes sense to think of the new thread as in the dynamic contour
> of the parent thread.

It makes perfect sense.

You could as well claim: since a local function could be executing
after its enclosing scope has exited, it makes no sense to let it
refer to lexical variables of that scope. The solution is to not tie
the lifetime of the variables so tightly with their scope: if they are
used by local functions, they live appropriately longer, as long as
any function which needs them exists.

It's similar with threads and dynamic variables. A local thread could
use the dynamic variables after their scope has exited; so what? The
solution is to not tie the lifetime of the bindings so tightly with
their scope: if they are used by local threads, they live appropriately
longer, as long as any thread which needs them exists.

I understand that it could be harder to implement efficiently, but it
definitely makes sense conceptually. Closures were also once thought
to be too inefficient to be implemented properly...

This is not specific to threads. The same applies to dynamic closures
in general (which don't exist in Common Lisp). I've even found a use
of them: for lazy variables (which don't exist in Common Lisp either)
it makes sense to evaluate them in the dynamic environment from the
point of their definition, rather than from the point of their first
access. The intent of a lazy variable is that it evaluates to the same
value no matter when it's first needed, but this is enforced only in
purely functional languages. Otherwise it should be ensured by the
programmer, and this is easier when the dynamic environment is taken
from the point of their definition.

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: jayessay
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <m3u0bwam7h.fsf@rigel.goldenthreadtech.com>
verec <·····@mac.com> writes:

> But then, I get nit-picked about threads and conditions and
> what-not.
> 
> You know what: that's missing the point entirely. Sure

This isn't the land of "worse is better".


> threading and conditions are valid issues, but so is the
> fact that wou won't run out of memory, or disk space, and
> that your ISP just didn't disconect you...

The "concerns" you list _are_ totally irrelevant, but threading isn't
- especially in the context of web programming.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d18d7d$0$87291$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 00:54:28 +0000, Pascal Bourguignon <····@mouse-potato.com> said:

> The same as with my solution: if there is another thread, it'll see
> the changed dynamic binding.
> Worse than with my solution: if there's an error or an interruption
> between the two setf symbol-function, the rebound binding will be
> left.  At least you should use UNWIND-PROTECT!

Assuming you were to use Sven Van Caekenberghe's excellent
s-sysdeps utility:

http://homepage.mac.com/svc/s-sysdeps/

It seems to run on allegro, lispworks and openmcl at the moment.

I believe that tis version is both thread and condition safe?
(asdf :s-sysdeps)

(defparameter *rebind-lock* (s-sysdeps:make-process-lock "rebind-lock"))

(defun rebind-me ()
  (format t "rebind me~%"))

(defun test3 ()
  (s-sysdeps:with-process-lock (*rebind-lock*)
    (let ((old (symbol-function 'rebind-me)))
      (unwind-protect
          (progn
            (rebind-me)
            (setf (symbol-function 'rebind-me) (lambda () (format t 
"rebound!~%")))
            (rebind-me))
        (progn
          (setf (symbol-function 'rebind-me) old)
          (rebind-me))))))

CL-USER 8 > (test3)
rebind me
rebound!
rebind me
ni

--
JFB
From: Thomas F. Burdick
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <xcvirsd2641.fsf@conquest.OCF.Berkeley.EDU>
"Stefan Kamphausen" <······@gmx.de> writes:

> first I hope I got the subject right: I think I am looking for a way to
> dynamically bind functions just the way I can do it with dynamic
> variables.
> 
...
>   ;; low level function that should be rebound
>   (defun rebindme ()
>     (format t "Rebind me, please~%"))

If control the definitions of all the functions you want to make
dynamically bindable, you can just indirect through a special variable:

  (defmacro defun* (name lambda-list &body body)
    (let ((var (gensym (string name))))
      `(progn
         (declaim (type function ,var))
         (defparameter ,var (lambda ,lambda-list (block ,name ,@body)))
         (setf (get ',name 'special-function) ',var)
         (declaim (inline ,name))
         (defun ,name (&rest args)
           (apply ,var args)))))
  
  (defmacro fluid-labels (flets &body body)
    `(progv (list ,@(loop for (name) in flets collect `(get ',name 'special-function)))
            (list ,@(loop for (name lambda-list . body) in flets
                          collect `(lambda ,lambda-list (block ,name ,@body))))
       ,@body))

Then you'd instead write:

  (defun* rebindme ()
    (format t "Rebind me, please~%"))

>   ;; higher level function which calls the low level defun
>   (defun test-rebinding ()
>     (format t "test-rebinding calls rebindme~%")
>     (rebindme))
> 
>   ;; test function that should locally override the low level function
>   (defun can-not-rebind-it ()
>     (test-rebinding)
>     (flet ((rebindme ()
>              (format t "This get's deleted by compiler~%")))
>       (test-rebinding))
>     (test-rebinding))

  (defun rebind-it ()
    (fluid-labels ((rebindme ()
                     (format t "This gets called instead~%")))
      (test-rebinding))
    (test-rebinding))

Generally, if you want to bind something dynamically, you can figure
out some way of indirecting through a special variable, which will
give you the same semantics for your special function, or whatever,
that you get in the same implementation for a special variable.  And
you don't have to turn off the ability of having other threads get
scheduled.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Michael Price
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <slrndt3iv9.2b8.malus42@yahoo.com>
On 2006-01-20, Stefan Kamphausen <······@gmx.de> wrote:
>    ;; low level function that should be rebound
>    (defun rebindme ()
>      (format t "Rebind me, please~%"))
> 
>    ;; higher level function which calls the low level defun
>    (defun test-rebinding ()
>      (format t "test-rebinding calls rebindme~%")
>      (rebindme))
> 
>    ;; test function that should locally override the low level function
>    (defun can-not-rebind-it ()
>      (test-rebinding)
>      (flet ((rebindme ()
>               (format t "This get's deleted by compiler~%")))
>        (test-rebinding))
>      (test-rebinding))
> 
>  As you can see if you compile it the flet'ed function get's deleted

This will probably be followed by a bunch of posts telling you never to do
this because it doesn't really do what you want, especially when
multithreaded, but you can always cheat:

CL-USER> (defun rebindme ()
           (format t "Rebind me, please~%"))

REBINDME
CL-USER> (defun test-rebinding ()
           (format t "test-rebinding calls rebindme~%")
           (rebindme))

TEST-REBINDING
CL-USER> (defun lets-cheat ()
           (let ((old-function (symbol-function 'rebindme)))
             (test-rebinding)
             (setf (symbol-function 'rebindme)
                   (lambda () (format t "Hi, I'm new here.~%")))
             (test-rebinding)
             (setf (symbol-function 'rebindme) old-function)
             (test-rebinding)))

LETS-CHEAT
CL-USER> (lets-cheat)
test-rebinding calls rebindme
Rebind me, please
test-rebinding calls rebindme
Hi, I'm new here.
test-rebinding calls rebindme
Rebind me, please
NIL
From: verec
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <43d1deac$0$87298$5a6aecb4@news.aaisp.net.uk>
On 2006-01-21 05:51:28 +0000, Michael Price <·······@yahoo.com> said:

> This will probably be followed by a bunch of posts telling you never to do
> this because it doesn't really do what you want, especially when
> multithreaded, but you can always cheat:
> 
> CL-USER> (defun rebindme ()
>            (format t "Rebind me, please~%"))
> 
> REBINDME
> CL-USER> (defun test-rebinding ()
>            (format t "test-rebinding calls rebindme~%")
>            (rebindme))
> 
> TEST-REBINDING
> CL-USER> (defun lets-cheat ()
>            (let ((old-function (symbol-function 'rebindme)))
>              (test-rebinding)
>              (setf (symbol-function 'rebindme)
>                    (lambda () (format t "Hi, I'm new here.~%")))
>              (test-rebinding)
>              (setf (symbol-function 'rebindme) old-function)
>              (test-rebinding)))

Not sure why but it feels, like ... déjà vu ...

Oh yes! Stupid me! That post of mine about 5 hours prior
to yours, which is both thread and condition safe ...

What was I thinking? :-)
--
JFB
From: Geoffrey Summerhayes
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <9IlAf.20713$924.280291@news20.bellglobal.com>
"verec" <·····@mac.com> wrote in message ······························@news.aaisp.net.uk...
>
> Not sure why but it feels, like ... d�j� vu ...
>
> Oh yes! Stupid me! That post of mine about 5 hours prior
> to yours, which is both thread and condition safe ...
>
> What was I thinking? :-)

Whoa, kill the motor, dude.

Remember NG servers don't all update instantly, I've seen
posts go missing for days...

--
Geoff
From: Ivan Boldyrev
Subject: Re: Dynamic function bindings
Date: 
Message-ID: <6ib9a3-fvl.ln1@ibhome.cgitftp.uiggm.nsc.ru>
On 9360 day of my life Stefan Kamphausen wrote:
> first I hope I got the subject right: I think I am looking for a way to
> dynamically bind functions just the way I can do it with dynamic
> variables.

This is simple homegrown solution.  It is not perfect (for example,
DEFDFUN is not 100% compatible with DEFUN: documentation string is
ignored, for example; DFLET doesn't check if FUNCNAME was declared
with DEFDFUN), but I spent so little time programming and testing
it... :)

;;; defdefun.lisp
;;;----------------------------------------------------------------------
;;;  (C) 2006 Ivan Boldyrev.  Do whatever you want.

(defmacro defdfun (funcname args &rest body)
  (let ((var (gensym)))
    `(progn
      (defvar ,var (lambda ,args ,@body))
      (eval-when (:load-toplevel :compile-toplevel :execute)
        (setf (get ',funcname 'defdfun)
              ',var))
      (defun ,funcname (&rest args)
        (apply ,var args)))))

(defmacro dflet ((funcname args &rest body1) &rest body2)
  `(let ((,(get funcname 'defdfun) (lambda ,args ,@body1)))
    ,@body2))

;;;----------------------------------------------------------------------

Examples:

(defdfun dtest (x)
  (format t "Toplevel definition.  Argument is ~S~%" x))

(defun helper (x) (dtest (list x x)))

(defun tester ()
   (dflet (dtest (y)
              (format t "Dynamic definition.  Argument is ~S~%" y))
       (helper nil)))

> (dtest 1)
Toplevel definition. Argument is 1
> (tester)
Dynamic definition.  Argument is (NIL NIL)
 
-- 
Ivan Boldyrev

                  Sorry my terrible English, my native language is Lisp!