From: ············@gmail.com
Subject: what flet doesn't work here??
Date: 
Message-ID: <1166864905.011817.185170@42g2000cwt.googlegroups.com>
Hello:

CL-USER 3 : 1 > (defun a () "a1")
A

CL-USER 4 : 1 > (defun b () (a))
B

CL-USER 5 : 1 > (b)
"a1"

CL-USER 6 : 1 > (flet ((a () "a2")) (b))
"a1"

I suppose it should print a2, but it still prints a1.
why??

Thanks

From: Michal Krupka
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <emit4d$ctk$1@aioe.org>
On 2006-12-23 10:08:25 +0100, ·············@gmail.com" 
<············@gmail.com> said:

> Hello:
> 
> CL-USER 3 : 1 > (defun a () "a1")
> A
> 
> CL-USER 4 : 1 > (defun b () (a))
> B
> 
> CL-USER 5 : 1 > (b)
> "a1"
> 
> CL-USER 6 : 1 > (flet ((a () "a2")) (b))
> "a1"
> 
> I suppose it should print a2, but it still prints a1.
> why??
> 
> Thanks


(flet ((b () "a2")) (b))

is better

Michal
From: ············@gmail.com
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <1166867195.645197.322510@i12g2000cwa.googlegroups.com>
Michal Krupka ¼g¹D¡G

> (flet ((b () "a2")) (b))
> is better
> Michal
   I see, but what I want is replacing the current definition of a
pre-defined function, that's why I use flet with a.
From: Rob Warnock
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <iKadnXFKSb4hYBHYnZ2dnUVZ_uuqnZ2d@speakeasy.net>
············@gmail.com <············@gmail.com> wrote:
+---------------
| Michal Krupka �g�D�G
| 
| > (flet ((b () "a2")) (b))
| > is better
| I see, but what I want is replacing the current definition of a
| pre-defined function, that's why I use flet with a.
+---------------

In ANSI CL[1], functions are scoped lexically, not dynamically.


-Rob

[1] Yes, I am aware of the thread on "dynamically scoped functions"
    and "DFLET" we had here several years ago [Google should have it,
    start with <···································@news.netcologne.de>],
    but many of the proposals for adding dynamically scoped functions
    discussed there required that the functions to be shadowed be
    defined originally with some idiosyncratic macro, *not* CL:DEFUN.
    And it certainly wouldn't work to shadow some function that had
    been compiled (with CL:DEFUN) in a separate compilation unit,
    since it might have been silently inlined in various places.

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Michal Krupka
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <emj2e4$npv$1@aioe.org>
On 2006-12-23 10:46:35 +0100, ·············@gmail.com" 
<············@gmail.com> said:

> 
> Michal Krupka �g�D�G
> 
>> (flet ((b () "a2")) (b))
>> is better
>> Michal
>    I see, but what I want is replacing the current definition of a
> pre-defined function, that's why I use flet with a.

Sorry, I read your question too quickly. Rob is right, functions have 
lexical scope.

Michal
From: Ron Garret
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <rNOSPAMon-86FB84.12520323122006@news.gha.chartermi.net>
In article <············@aioe.org>, Michal Krupka <·······@mac.com> 
wrote:

> On 2006-12-23 10:46:35 +0100, ·············@gmail.com" 
> <············@gmail.com> said:
> 
> > 
> > Michal Krupka �g�D�G
> > 
> >> (flet ((b () "a2")) (b))
> >> is better
> >> Michal
> >    I see, but what I want is replacing the current definition of a
> > pre-defined function, that's why I use flet with a.
> 
> Sorry, I read your question too quickly. Rob is right, functions have 
> lexical scope.
> 
> Michal

The wonderful thing about CL is that it imposes very few constraints 
that cannot be dispensed with in a few lines of code:

(defmacro ddefun (fname args &body body)
  `(progn
     (defvar ,fname (lambda ,args ,@body))
     (defun ,fname (&rest args) (apply ,fname args))))

(defmacro dflet (bindings &body body)
  `(let ,(mapcar (lambda (b) `(,(car b) (lambda ,(second b) ,@(cddr b))))
                  bindings)
     ,@body))


? (ddefun a () 'a)
A
? (ddefun b () (a))
B
? (b)
A
? (dflet ((a () 'c)) (b))
C
?
From: Rob Warnock
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <96OdnekPAoaQSRDYnZ2dnUVZ_sOknZ2d@speakeasy.net>
Ron Garret  <·········@flownet.com> wrote:
+---------------
| The wonderful thing about CL is that it imposes very few constraints 
| that cannot be dispensed with in a few lines of code:
| 
| (defmacro ddefun (fname args &body body) ...)
+---------------

Yes, but as I pointed out upthread, that only works if you use
DDEFUN to define *all* the functions you want to be able to later
use DFLET with. I got the impression the OP wanted to be able to
override functions already defined by other code [though I could
be mistaken], which your certainly nice macros can't help with.
[AFAIK, nothing can, in general.]


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ron Garret
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <rNOSPAMon-D67D9E.18293823122006@news.gha.chartermi.net>
In article <································@speakeasy.net>,
 ····@rpw3.org (Rob Warnock) wrote:

> Ron Garret  <·········@flownet.com> wrote:
> +---------------
> | The wonderful thing about CL is that it imposes very few constraints 
> | that cannot be dispensed with in a few lines of code:
> | 
> | (defmacro ddefun (fname args &body body) ...)
> +---------------
> 
> Yes, but as I pointed out upthread, that only works if you use
> DDEFUN to define *all* the functions you want to be able to later
> use DFLET with. I got the impression the OP wanted to be able to
> override functions already defined by other code [though I could
> be mistaken], which your certainly nice macros can't help with.
> [AFAIK, nothing can, in general.]

Piffle.

(defmacro dflet (bindings &body body)
  (loop for (fname . ignore) in bindings do
        (unless (member fname *dynamically-bound-functions*)
          (push fname *dynamically-bound-functions*)
          (eval `(progn
                   (defvar ,fname)
                   (setf ,fname ,(and (fboundp fname) `#',fname))
                   (defun ,fname (&rest args) (apply ,fname args))))))
  `(let ,(mapcar (lambda (b) `(,(car b) (lambda ,(second b) ,@(cddr b))))
                 bindings)
     ,@body))

? (defvar *DYNAMICALLY-BOUND-FUNCTIONS* '())
*DYNAMICALLY-BOUND-FUNCTIONS*
? (defun f1 () 'f1)
F1
? (defun f2 () (f1))
F2
? (dflet ((f1 () 'foo)) (f2))
FOO
? (f2)
F1
? 

rg
From: Pascal Costanza
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <4v768oF1aopabU1@mid.individual.net>
Ron Garret wrote:
> In article <································@speakeasy.net>,
>  ····@rpw3.org (Rob Warnock) wrote:
> 
>> Ron Garret  <·········@flownet.com> wrote:
>> +---------------
>> | The wonderful thing about CL is that it imposes very few constraints 
>> | that cannot be dispensed with in a few lines of code:
>> | 
>> | (defmacro ddefun (fname args &body body) ...)
>> +---------------
>>
>> Yes, but as I pointed out upthread, that only works if you use
>> DDEFUN to define *all* the functions you want to be able to later
>> use DFLET with. I got the impression the OP wanted to be able to
>> override functions already defined by other code [though I could
>> be mistaken], which your certainly nice macros can't help with.
>> [AFAIK, nothing can, in general.]
> 
> Piffle.
> 
> (defmacro dflet (bindings &body body)
>   (loop for (fname . ignore) in bindings do
>         (unless (member fname *dynamically-bound-functions*)
>           (push fname *dynamically-bound-functions*)
>           (eval `(progn
>                    (defvar ,fname)
>                    (setf ,fname ,(and (fboundp fname) `#',fname))
>                    (defun ,fname (&rest args) (apply ,fname args))))))
>   `(let ,(mapcar (lambda (b) `(,(car b) (lambda ,(second b) ,@(cddr b))))
>                  bindings)
>      ,@body))

That's a neat hack at best. Rob talked about functions by other code. 
You shouldn't mess around with other code like that because you don't 
know what they do with these functions internally. (For example, the 
other code could use side effects on function cells as well, and then 
you will definitely get into trouble.)

And more specifically, you are definitely not allowed to change 
functions like that which are predefined by ANSI CL.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Ron Garret
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <rNOSPAMon-79AD8A.09340624122006@news.gha.chartermi.net>
In article <···············@mid.individual.net>,
 Pascal Costanza <··@p-cos.net> wrote:

> Ron Garret wrote:
> > In article <································@speakeasy.net>,
> >  ····@rpw3.org (Rob Warnock) wrote:
> > 
> >> Ron Garret  <·········@flownet.com> wrote:
> >> +---------------
> >> | The wonderful thing about CL is that it imposes very few constraints 
> >> | that cannot be dispensed with in a few lines of code:
> >> | 
> >> | (defmacro ddefun (fname args &body body) ...)
> >> +---------------
> >>
> >> Yes, but as I pointed out upthread, that only works if you use
> >> DDEFUN to define *all* the functions you want to be able to later
> >> use DFLET with. I got the impression the OP wanted to be able to
> >> override functions already defined by other code [though I could
> >> be mistaken], which your certainly nice macros can't help with.
> >> [AFAIK, nothing can, in general.]
> > 
> > Piffle.
> > 
> > (defmacro dflet (bindings &body body)
> >   (loop for (fname . ignore) in bindings do
> >         (unless (member fname *dynamically-bound-functions*)
> >           (push fname *dynamically-bound-functions*)
> >           (eval `(progn
> >                    (defvar ,fname)
> >                    (setf ,fname ,(and (fboundp fname) `#',fname))
> >                    (defun ,fname (&rest args) (apply ,fname args))))))
> >   `(let ,(mapcar (lambda (b) `(,(car b) (lambda ,(second b) ,@(cddr b))))
> >                  bindings)
> >      ,@body))
> 
> That's a neat hack at best. Rob talked about functions by other code. 
> You shouldn't mess around with other code like that because you don't 
> know what they do with these functions internally. (For example, the 
> other code could use side effects on function cells as well, and then 
> you will definitely get into trouble.)

The requirements as given required this kind of a hack.  You're saying 
that dynamically binding functions that have been defined in the normal 
way is a bad idea.  I do not disagree.  But Rob claimed it couldn't be 
done, and that's not true.

> And more specifically, you are definitely not allowed to change 
> functions like that which are predefined by ANSI CL.

Yes, figuring out how to make dflet (appear to) work for CL built-ins is 
left as an exercise.

rg
From: Rob Warnock
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <VaednaypjYip2xLYnZ2dnUVZ_h63nZ2d@speakeasy.net>
Ron Garret  <·········@flownet.com> wrote:
+---------------
| The requirements as given required this kind of a hack.  You're saying 
| that dynamically binding functions that have been defined in the normal 
| way is a bad idea.  I do not disagree.  But Rob claimed it couldn't be 
| done, and that's not true.
+---------------

Actually, it *is* true, in the sense of "can't be done portably or 
in a standard-conformant way", if the functions being redefined were
compiled elsewhere. Consider functions FOO & BAR in a separate file,
where BAR calls FOO and you try to rebind FOO:

    CHLS 3.2.2.3 Semantic Constraints
    ...
    A call within a file to a named function that is defined in the
    same file refers to that function, unless that function has been
    declared notinline. The consequences are unspecified if functions
    are redefined individually at run time or multiply defined in
    the same file.

The most likely and benign [and yet still "wrong"] consequence
is that the code for BAR has the absolute machine address of
FOO's machine code compiled into its body, and any redefinition
or shadowing of FOO *won't* change which code is actually
called by BAR.

Worse, if FOO *was* declared "inline", then this one [loc. cite]
prohibits it entirely:

     The definition of a function that is defined and declared inline
     in the compilation environment must be the same at run time.

There are other constraints in that section which limit what you
may change at run-time in a portable and standard-conformant way.

Again, my commments were/are in the context as I perceived it
of the OP's initial request, which was for a way at run-time to
individually override arbitrary functions in some random library
he'd loaded [a library written/provided by others]. It is *that*
which I was claiming "can't be done" in general, and probably not
in *any* implementation with a decent file compiler.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Costanza
Subject: Re: what flet doesn't work here??
Date: 
Message-ID: <4v62urF1ao4f6U1@mid.individual.net>
Rob Warnock wrote:
> Ron Garret  <·········@flownet.com> wrote:
> +---------------
> | The wonderful thing about CL is that it imposes very few constraints 
> | that cannot be dispensed with in a few lines of code:
> | 
> | (defmacro ddefun (fname args &body body) ...)
> +---------------
> 
> Yes, but as I pointed out upthread, that only works if you use
> DDEFUN to define *all* the functions you want to be able to later
> use DFLET with. I got the impression the OP wanted to be able to
> override functions already defined by other code [though I could
> be mistaken], which your certainly nice macros can't help with.
> [AFAIK, nothing can, in general.]

Yes, but the typical trick applies to just define a new package in which 
you shadow the functions that you want to turn into dynamic ones and 
redefine them accordingly.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/