From: Drew McDermott
Subject: What's the point of flet?
Date: 
Message-ID: <3BDF119D.A51C178B@yale.edu>
Does anyone actually use flet (as opposed to labels)?

The only use I can think of for it is to override the definition of an
existing function.  E.g.:

(flet ((car (x)
         (cond ((consp x) (car x))
               ((stringp x) (elt x 0))
               ((integerp x)
                (do ((y x (truncate y 10))
                     (prev 0 y))
                    ((= y 0)
                     (cond ((= prev 0)
                            (error "Can't take car of 0"))
                           (t (abs prev))))))
               (t (error ...)))))
  ...)

I've never wanted to do anything like this myself, but I'm idly
curious whether anyone else has.

                                           -- Drew McDermott

From: Coby Beck
Subject: Re: What's the point of flet?
Date: 
Message-ID: <DfFD7.525230$8c3.89139179@typhoon.tampabay.rr.com>
"Drew McDermott" <··············@yale.edu> wrote in message
······················@yale.edu...
> Does anyone actually use flet (as opposed to labels)?
>

Yes, I rarely use labels - only when I need recursion.  No deep philisophical
reason, just because....

> The only use I can think of for it is to override the definition of an
> existing function.  E.g.:
>

Won't labels do that as well?

Coby
--
(remove #\space "coby . beck @ opentechgroup . com")
From: Thomas F. Burdick
Subject: Re: What's the point of flet?
Date: 
Message-ID: <xcvsnc0hi9v.fsf@hurricane.OCF.Berkeley.EDU>
"Coby Beck" <·····@mercury.bc.ca> writes:

> "Drew McDermott" <··············@yale.edu> wrote in message
> ······················@yale.edu...
> > Does anyone actually use flet (as opposed to labels)?

Unless I need LABELS, I use FLET.  I could certainly do it the other
way around, but I like the fact that FLET works just like LET, but for
functions.  LABELS is somewhat of a different animal.  Come to think
of it, FLET* might also be nice to have.  But I guess if it hadn't
occured to me when I was writing code, I probably don't have much use
for it.

> > The only use I can think of for it is to override the definition of an
> > existing function.  E.g.:
> >
> 
> Won't labels do that as well?

Sort of, but I'm guessing you didn't read his example.  This will work:

  (defmacro with-fussy-cdr (&body forms)
    `(flet ((cdr (cons)
              (unless (consp cons)
                (error "I'm fussy"))
              (cdr cons)))
       ,@forms))

This, on the other hand, will get stuck in an infinite recursion:

  (defmacro with-fussy-cdr (&body forms)
    `(labels ((cdr (cons)
                (unless (consp cons)
                  (error "I'm fussy"))
                (cdr cons)))
       ,@forms))

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Erik Naggum
Subject: Re: What's the point of flet?
Date: 
Message-ID: <3213492447303997@naggum.net>
* Thomas F. Burdick
| Sort of, but I'm guessing you didn't read his example.  This will work:
:
| This, on the other hand, will get stuck in an infinite recursion:

  No.  Both should have only and exactly _no_ effect.  A Common Lisp
  compiler has every right to assume that you will _not_ redefine car and
  cdr or any other symbols in the COMMON-LISP package with a standard
  function binding and can therefore do whatever it pleases with calls to
  such functions without consulting their function definition.

  Try again with a user-defined function, instead.

///
-- 
  Norway is now run by a priest from the fundamentalist Christian People's
  Party, the fifth largest party representing one eighth of the electorate.
-- 
  Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
From: Thomas F. Burdick
Subject: Re: What's the point of flet?
Date: 
Message-ID: <xcvofmocogj.fsf@apocalypse.OCF.Berkeley.EDU>
Erik Naggum <····@naggum.net> writes:

> * Thomas F. Burdick
> | Sort of, but I'm guessing you didn't read his example.  This will work:
> :
> | This, on the other hand, will get stuck in an infinite recursion:
> 
>   No.  Both should have only and exactly _no_ effect.  A Common Lisp
>   compiler has every right to assume that you will _not_ redefine car and
>   cdr or any other symbols in the COMMON-LISP package with a standard
>   function binding and can therefore do whatever it pleases with calls to
>   such functions without consulting their function definition.

Well, yes, obviously.  If you really wanted to do this, you'd have to
shadow cdr and define it yourself (as I did in a later post).

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Barry Margolin
Subject: Re: What's the point of flet?
Date: 
Message-ID: <QmFD7.33$hi1.630@burlma1-snr2>
In article <·························@typhoon.tampabay.rr.com>,
Coby Beck <·····@mercury.bc.ca> wrote:
>
>"Drew McDermott" <··············@yale.edu> wrote in message
>······················@yale.edu...
>> The only use I can think of for it is to override the definition of an
>> existing function.  E.g.:
>>
>
>Won't labels do that as well?

I think what he meant was "augment" rather than "override", like an :AROUND
method.  If you use LABELS, when you try to call the real version it will
just recurse into your replacement.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Coby Beck
Subject: Re: What's the point of flet?
Date: 
Message-ID: <nqFD7.525232$8c3.89150371@typhoon.tampabay.rr.com>
"Coby Beck" <·····@mercury.bc.ca> wrote in message
······························@typhoon.tampabay.rr.com...
>
> "Drew McDermott" <··············@yale.edu> wrote in message
> ······················@yale.edu...
> > Does anyone actually use flet (as opposed to labels)?
> >
>
> Yes, I rarely use labels - only when I need recursion.  No deep philisophical
> reason, just because....
>
> > The only use I can think of for it is to override the definition of an
> > existing function.  E.g.:
> >
>
> Won't labels do that as well?
>
> Coby

Sorry, I think I just got the distinction you mean, ie use the former
definition internally while redefining externally.  Seems like a strange design
goal....

I prefer flet mostly because of familiarity and the logic of its name -
f(unction)let.
From: Drew McDermott
Subject: Re: What's the point of flet?
Date: 
Message-ID: <3BE02AFA.42A70ED8@yale.edu>
Coby Beck wrote:

> "Drew McDermott" <··············@yale.edu> wrote in message
> ······················@yale.edu...
> > Does anyone actually use flet (as opposed to labels)?
> >
>
> Yes, I rarely use labels - only when I need recursion.  No deep philisophical
> reason, just because....

But if you write 'labels' every time, you can let the compiler worry about
recursion.  If a function defined by 'labels' isn't actually recursive, I assume
the compiler produces exactly the same code as it would if the function were
defined by 'flet'.

>
> > The only use I can think of for it is to override the definition of an
> > existing function.  E.g.:
> >

>
> Won't labels do that as well?

Yes, I should have said "augment," as several people have pointed out.  Of
course, you can augment with 'labels' too, if you're willing to write a bit more:

(labels ((builtin-car (x) (car x)))
    (labels ((car (x) (cond ((consp x) (builtin-car x)) ...)))
        etc. etc.))

       -- Drew McDermott
From: Jochen Schmidt
Subject: Re: What's the point of flet?
Date: 
Message-ID: <9rpbfi$2rl$1@rznews2.rrze.uni-erlangen.de>
Drew McDermott wrote:

> Coby Beck wrote:
> 
>> "Drew McDermott" <··············@yale.edu> wrote in message
>> ······················@yale.edu...
>> > Does anyone actually use flet (as opposed to labels)?
>> >
>>
>> Yes, I rarely use labels - only when I need recursion.  No deep
>> philisophical reason, just because....
> 
> But if you write 'labels' every time, you can let the compiler worry about
> recursion.  If a function defined by 'labels' isn't actually recursive, I
> assume the compiler produces exactly the same code as it would if the
> function were defined by 'flet'.

Programs are not only read by compilers but too by programmers - if you use
FLET the reader recognizes easier that it is not a recursive definition - 
or to the contrary - if I read LABELS then I immediately think that the 
function is meant to be recursive. It simply makes the intention explicit.

>> > The only use I can think of for it is to override the definition of an
>> > existing function.  E.g.:
>> >
> 
>>
>> Won't labels do that as well?
> 
> Yes, I should have said "augment," as several people have pointed out.  Of
> course, you can augment with 'labels' too, if you're willing to write a
> bit more:
> 
> (labels ((builtin-car (x) (car x)))
>     (labels ((car (x) (cond ((consp x) (builtin-car x)) ...)))
>         etc. etc.))

So much hassle only to circumvent to use FLET? I don't think CL lies much
emphasis on artificially reducing the set of builtins to an amount were it 
is only merely usable... 

ciao,
Jochen

--
http://www.dataheaven.de
From: Drew McDermott
Subject: Re: What's the point of flet?
Date: 
Message-ID: <3BE44947.1A4A1079@yale.edu>
Jochen Schmidt wrote:

>
> Programs are not only read by compilers but too by programmers - if you use
> FLET the reader recognizes easier that it is not a recursive definition -
> or to the contrary - if I read LABELS then I immediately think that the
> function is meant to be recursive. It simply makes the intention explicit.
>

I'ts interesting what different people find important.  I never use let* because
it obscures the dependence of variables on each other.  Most people don't care
about that; but apparently many do care that labels obscures the dependence of
functions on each other (and themselves).  I guess I'll have to start using flet
to be consistent.

[me]
> Yes, I should have said "augment," as several people have pointed out.  Of

> > course, you can augment with 'labels' too, if you're willing to write a
> > bit more:
> >
> > (labels ((builtin-car (x) (car x)))
> >     (labels ((car (x) (cond ((consp x) (builtin-car x)) ...)))
> >         etc. etc.))
>

[Jochen Schmidt]

> So much hassle only to circumvent to use FLET?

You misunderstood me. I would certainly use FLET for this purpose in practice.

    -- Drew McDermott
From: Kaz Kylheku
Subject: Re: What's the point of flet?
Date: 
Message-ID: <YQ6F7.12187$Ud.361786@news1.rdc1.bc.home.com>
In article <·················@yale.edu>, Drew McDermott wrote:
[ re-formatted to 79 columns ]

>I'ts interesting what different people find important.  I never use
>let* because it obscures the dependence of variables on each other.

let* ensures that bindings are performed in order, allowing the
initializing expression to refer to the variables bound by lexically
prior bindings. What is obscure about an identifier being in
visible to expressions that follow?

I think that if let were renamed let*, and vice versa, and if most Lisp
code typically used let rather than let*, then you'd complain about
let* ``obscuring'' parallel initialization.  Anything which provides
an infrequently invoked variation on behavior can be said to obscure
that behavior.

Irrational concerns lead one to choose some suboptimal alternative in a
circumstance where the eschewed solution is best. Do not allow
yourself to have irrational concerns.

>Most people don't care about that; but apparently many do care that labels
>obscures the dependence of functions on each other (and themselves).

s/obscures/permits/
From: Kent M Pitman
Subject: Re: What's the point of flet?
Date: 
Message-ID: <sfwy9lsyb89.fsf@world.std.com>
Drew McDermott <··············@yale.edu> writes:

> Does anyone actually use flet (as opposed to labels)?
> 
> The only use I can think of for it is to override the definition of an
> existing function.  E.g.:
> 
> (flet ((car (x)
>          (cond ((consp x) (car x))
>                ((stringp x) (elt x 0))
>                ((integerp x)
>                 (do ((y x (truncate y 10))
>                      (prev 0 y))
>                     ((= y 0)
>                      (cond ((= prev 0)
>                             (error "Can't take car of 0"))
>                            (t (abs prev))))))
>                (t (error ...)))))
>   ...)
> 
> I've never wanted to do anything like this myself, but I'm idly
> curious whether anyone else has.

I often use it when I don't plan to do something recursive.  But in most
of those cases LABELS would suffice, so I guess that's not your question.

However, the one case where it is used is where you want to not just 
override but augment a function.  e.g., consider the following idiomatic
way of creating a lexical piece of information...

 (defun internal-lexically-bound-frob-p (x) nil)

 (defmacro lexically-bound-frob-p (x) `(internal-lexically-bound-frob-p ',x))

 (defmacro with-lexically-bound-frob (name &body forms)
   `(flet ((internal-lexically-bound-frob-p (x)
             (or (eq x ',name) (lexically-bound-frob-p x))))
      ,@forms))

 ;; usage tests follow

 (lexically-bound-frob-p foo)     ;No lexical frob binding
 => NIL

 (with-lexically-bound-frob foo   ;Lexical frob binding
   (lexically-bound-frob-p foo))
 => T

 (let ((x #'(lambda () (lexically-bound-frob-p foo))))
   (with-lexically-bound-frob foo ;Frob binding dynamically surrounds but
     (funcall x)))                ;doesn't lexically surround the test.
 => NIL


(I'd actually normally have used FLET in this last example, but you
might have found that confusing given the nature of your question, so
I worked around it.)
From: Jochen Schmidt
Subject: Re: What's the point of flet?
Date: 
Message-ID: <9rn8v8$rnu$1@rznews2.rrze.uni-erlangen.de>
Drew McDermott wrote:

> Does anyone actually use flet (as opposed to labels)?

Yes I use it sometimes.
LABELS is to FLET what LET* is to LET.
I only use LET* or LABELS over their simpler counterparts if it is _really_ 
needed, so if you read a FLET you know for sure that the function is not 
self-recursive or that noone of the multiple locally defined function 
depend on each other (in terms of being caller/callee).

But probably your question was more on if there is a need at all for
local functions that are not self-recursive or do not call each other.
I sometimes use FLET to break a growing function up into smaller more
readable parts if the parts have no real use to justify being a global 
accessible function. IMHO this makes code more readable than big, nested 
control-blocks. This only works to some extent - at some point rethinking
the approach and appropriately abstracting out the general concepts is a
better idea.

> The only use I can think of for it is to override the definition of an
> existing function.  E.g.:

I never needed that...

ciao,
Jochen

--
http://www.dataheaven.de
From: Vebjorn Ljosa
Subject: Re: What's the point of flet?
Date: 
Message-ID: <cy3pu74fg8c.fsf@ljosa.com>
* Jochen Schmidt <···@dataheaven.de>
| I sometimes use FLET to break a growing function up into smaller more
| readable parts if the parts have no real use to justify being a global 
| accessible function. IMHO this makes code more readable than big, nested 
| control-blocks. This only works to some extent - at some point rethinking
| the approach and appropriately abstracting out the general concepts is a
| better idea.

But it also makes the parts impossible to test separately.  I
therefore only use FLET when the subfunctions are very simple or when
it's beneficial to place the subfunction within the static scope of
the main function.

I sometimes use names starting with "%" for functions that should
really be part of their caller, but which I have moved out for
readability or ease of debugging.  When reading the code, the percent
sign tells me that I should not try to understand the function as a
building block of it's own, that it only makes sense in the context of
its caller.

-- 
Vebjorn Ljosa
Department of Computer Science
University of California, Santa Barbara
From: Kent M Pitman
Subject: Re: What's the point of flet?
Date: 
Message-ID: <sfwd7341cf3.fsf@world.std.com>
Vebjorn Ljosa <·····@ljosa.com> writes:

> * Jochen Schmidt <···@dataheaven.de>
> | I sometimes use FLET to break a growing function up into smaller more
> | readable parts if the parts have no real use to justify being a global 
> | accessible function. IMHO this makes code more readable than big, nested 
> | control-blocks. This only works to some extent - at some point rethinking
> | the approach and appropriately abstracting out the general concepts is a
> | better idea.
> 
> But it also makes the parts impossible to test separately.

I don't understand.  Nothing keeps you from FLET'ing some test
functions, too. ;-)
From: Tim Bradshaw
Subject: Re: What's the point of flet?
Date: 
Message-ID: <nkj3d40t7qw.fsf@omega.tardis.ed.ac.uk>
Vebjorn Ljosa <·····@ljosa.com> writes:

> But it also makes the parts impossible to test separately.  I
> therefore only use FLET when the subfunctions are very simple or when
> it's beneficial to place the subfunction within the static scope of
> the main function.

If the parts rely on lexical state from the parent function then they
are untestable in isolation anyway.  I do this quite a lot.

--tim
From: Erik Naggum
Subject: Re: What's the point of flet?
Date: 
Message-ID: <3213554492332963@naggum.net>
* Vebjorn Ljosa <·····@ljosa.com>
| But it also makes the parts impossible to test separately.

  You may simply need a better Common Lisp environment.

  Suppose you have this silly function:

(defun foo ()
  (flet ((bar () t))
    (bar)))

  In Allegro CL, this defines two functions reachable with fdefinition: one
  named by the symbol foo, and one named by the list (flet foo bar).  That
  is, #'(flet foo bar) returns the inner function bar.  If this is not a
  closure, it is funcallable.

(funcall #'(flet foo bar))
=> t

  You can trace inner functions and use these function names in a number of
  interesting places.  I think this is a very useful and intelligent
  extension to the function name concept, given that it has to be supported
  for setf methods.

///
-- 
  Norway is now run by a priest from the fundamentalist Christian People's
  Party, the fifth largest party representing one eighth of the electorate.
-- 
  Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
From: Vebjorn Ljosa
Subject: Re: What's the point of flet?
Date: 
Message-ID: <cy3elnjp8p8.fsf@ljosa.com>
* Erik Naggum <····@naggum.net>
| * Vebjorn Ljosa <·····@ljosa.com>
| | But it also makes the parts impossible to test separately.
| 
|   You may simply need a better Common Lisp environment.

Turns out I simple needed better knowledge of my Common Lisp
environment. :)  Thanks.

-- 
Vebjorn Ljosa
From: Pekka P. Pirinen
Subject: Re: What's the point of flet?
Date: 
Message-ID: <upu72sa10.fsf@globalgraphics.com>
Erik Naggum <····@naggum.net> writes:
> * Vebjorn Ljosa <·····@ljosa.com>
> | But it also makes the parts impossible to test separately.
> 
>   You may simply need a better Common Lisp environment.
> 
>   Suppose you have this silly function:
> 
> (defun foo ()
>   (flet ((bar () t))
>     (bar)))
> 
>   In Allegro CL, this defines two functions reachable with fdefinition: one
>   named by the symbol foo, and one named by the list (flet foo bar).  That
>   is, #'(flet foo bar) returns the inner function bar.

Interesting that they should extend the standard to access these.
LispWorks has the same functionality, because it's needed for the
development tools, but we gave it a specific interface:
  (dspec:dspec-function-object '(subfunction bar foo))
Sadly, most of the DSPEC package is still not documented for users.

That function is actually so simple that the compiler will inline BAR
(even at DEBUG 3), not creating a function object that could be
returned.  If you want to experiment, use:

 (defun foo ()
   (flet ((bar () t))
     #'bar))


>   You can trace inner functions and use these function names in a number of
>   interesting places.  I think this is a very useful and intelligent
>   extension to the function name concept,

In LW, you can trace them as well, find definitions, etc.  Making
FUNCTION etc. return them would be very simple, but I'm not sure it's
actually a good idea extend the standard for the sake of a debugging
trick.  Extending function names is a useful idea, and there ought to
be a standard.  The LW DSPEC system actually goes all the way and
covers all types of definitions, not just the various kinds of
functions.  Xanalys could publish the spec.
-- 
Pekka P. Pirinen, Global Graphics Software, Cambridge, UK
Heard at OOPSLA 2000: We didn't pick the best solution [for the architecture],
because it would have required C++ programmers who understand the language.
From: Duane Rettig
Subject: Re: What's the point of flet?
Date: 
Message-ID: <4668u5pe2.fsf@beta.franz.com>
···············@globalgraphics.com (Pekka P. Pirinen) writes:

> Erik Naggum <····@naggum.net> writes:
> > * Vebjorn Ljosa <·····@ljosa.com>
> > | But it also makes the parts impossible to test separately.
> > 
> >   You may simply need a better Common Lisp environment.
> > 
> >   Suppose you have this silly function:
> > 
> > (defun foo ()
> >   (flet ((bar () t))
> >     (bar)))
> > 
> >   In Allegro CL, this defines two functions reachable with fdefinition: one
> >   named by the symbol foo, and one named by the list (flet foo bar).  That
> >   is, #'(flet foo bar) returns the inner function bar.
> 
> Interesting that they should extend the standard to access these.
> LispWorks has the same functionality, because it's needed for the
> development tools, but we gave it a specific interface:
>   (dspec:dspec-function-object '(subfunction bar foo))
> Sadly, most of the DSPEC package is still not documented for users.

In Allegro CL it is documented:

http://www.franz.com/support/documentation/6.1/doc/implementation.htm#function-specs-1

and especially

http://www.franz.com/support/documentation/6.1/doc/pages/operators/excl/def-function-spec-handler.htm

plus other sundry operators.  It should be easy enough to create a
"subfunction" function-spec handler in Allegro CL (although the
implementor of such a compatibility handler would have to know
some of the internals of how flets are stored in order to know
how to access them).

> >   You can trace inner functions and use these function names in a number of
> >   interesting places.  I think this is a very useful and intelligent
> >   extension to the function name concept,
> 
> In LW, you can trace them as well, find definitions, etc.  Making
> FUNCTION etc. return them would be very simple,

In fact, it should be automatic - if you implement #'(setf foo) as
a DSPEC, then you would tend to get #'(subfunction bar foo) for free
(i.e. with only a specific subfunction dspec definition).  What we did
in Allegro CL was to enhance the definition of "function name" in the
Ansi Spec.  We call the list form of a function name a "function spec"
and thus (setf foo) is a part of this generalization.  Other fspec
definition types we define include labels, method, :discriminator,
:effective-method, :top-level-form, :efft (external-format filled
template), :internal, etc.

> but I'm not sure it's
> actually a good idea extend the standard for the sake of a debugging
> trick.

That's not why we did it, though it is certainly a great side effect.
Whatever reasons you can think of for naming functions (including
debugging) are good reasons for adding such an extension.  Internally,
we use function specs for programmatic access to function objects.
Think of it as an intern mechanism for listified function names.

>  Extending function names is a useful idea, and there ought to
> be a standard.  The LW DSPEC system actually goes all the way and
> covers all types of definitions, not just the various kinds of
> functions.  Xanalys could publish the spec.

Yes, I'd be interested to see what other kinds of general definiton
specifications you find useful.  Are you talking about some kind of
"define" capability a la Scheme or Dylan?

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Pekka P. Pirinen
Subject: Re: What's the point of flet?
Date: 
Message-ID: <uvggtgm86.fsf@globalgraphics.com>
Duane Rettig <·····@franz.com> writes:
> ···············@globalgraphics.com (Pekka P. Pirinen) writes:
> > >   You can trace inner functions and use these function names [...]
> > 
> > In LW, you can trace them as well, find definitions, etc.  Making
> > FUNCTION etc. return them would be very simple,
> 
> In fact, it should be automatic - if you implement #'(setf foo) as
> a DSPEC, then you would tend to get #'(subfunction bar foo) for free

Yes, only the implementation of #'(SETF FOO) precedes the current
dspec system by almost a decade, and just special-cases (SETF FOO).
But it would be relatively easy to slot in the dspec system (there are
issues about speed and shakability that would have to be addressed).

> What we did in Allegro CL was to enhance the definition of "function
> name" in the Ansi Spec.  We call the list form of a function name a
> "function spec" and thus (setf foo) is a part of this
> generalization.  Other fspec definition types we define include
> labels, method, :discriminator, :effective-method, :top-level-form,
> :efft (external-format filled template), :internal, etc.

One ends up creating and naming different kinds of function object, so
it's only good design to create a system.  Liquid has one, too.
Unfortunately, the kinds and the names end up being different in every
implementation.  On some level, the users won't care about the
distinctions.  Hence, SUBFUNCTION.

Moreover, the definition classes form a hierarchy, so for example the
DEFMACRO class is a subclass of FUNCTION and DEFCLASS a subclass of
TYPE.  With a suitable mix of generality and extensibility, we were
able to use the definition spec system on both LW and Liquid.  This is
important, because it supports the tools of the LW IDE that runs on
both.  So, it has slightly wider aims than function specs.

> >  Extending function names is a useful idea, and there ought to
> > be a standard.  The LW DSPEC system actually goes all the way and
> > covers all types of definitions, not just the various kinds of
> > functions.  Xanalys could publish the spec.
> 
> Yes, I'd be interested to see what other kinds of general definiton
> specifications you find useful.  Are you talking about some kind of
> "define" capability a la Scheme or Dylan?

Nah (although there is an UNDEFINE method on dspecs :-), like I
explained above, it's more for supporting development tools.  The most
useful applications are support for tracing and source code location
finding.  It would be interesting to consider what extensions it could
contribute on the language level in addition this #' thing.

It's really up to Xanalys to publish more, and I can't speak for them
anymore.


Have a nice holiday,

 Pekka P. Pirinen, Global Graphics Software

 The great problem with Lisp is that it is just good enough to keep us
 from developing something really good.  - Alan Kay
From: Alain Picard
Subject: Re: What's the point of flet?
Date: 
Message-ID: <86elnhe5pg.fsf@gondolin.local.net>
···············@globalgraphics.com (Pekka P. Pirinen) writes:

> LispWorks has the same functionality, because it's needed for the
> development tools, but we gave it a specific interface:
>   (dspec:dspec-function-object '(subfunction bar foo))
> Sadly, most of the DSPEC package is still not documented for users.
[snip]
> The LW DSPEC system actually goes all the way and
> covers all types of definitions, not just the various kinds of
> functions.  Xanalys could publish the spec.

Indeed.  I asked for this, once, to try to fix a bug in ILISP's
handling of the edit definition, next caller, etc. stuff.  I got
a quick answer which helped me in that one case, but was told
the spec would not be forthcoming.

Maybe all Xanalys users could plead for this information 
to be published?


-- 
It would be difficult to construe        Larry Wall, in  article
this as a feature.			 <·····················@netlabs.com>
From: Coby Beck
Subject: Re: What's the point of flet?
Date: 
Message-ID: <gUHE7.2153$y%2.769749@typhoon.tampabay.rr.com>
"Pekka P. Pirinen" <···············@globalgraphics.com> wrote in message
··················@globalgraphics.com...
> Erik Naggum
> >   You can trace inner functions and use these function names in a number of
> >   interesting places.  I think this is a very useful and intelligent
> >   extension to the function name concept,
>
> In LW, you can trace them as well,

I  would love to hear how.

Coby
--
(remove #\space "coby . beck @ opentechgroup . com")
From: Pekka P. Pirinen
Subject: Re: What's the point of flet?
Date: 
Message-ID: <uk7x2v9he.fsf@globalgraphics.com>
"Coby Beck" <·····@mercury.bc.ca> writes:
> "Pekka P. Pirinen" <···············@globalgraphics.com> wrote in message
> ··················@globalgraphics.com...
> > Erik Naggum
> > >   You can trace inner functions [...]
> >
> > In LW, you can trace them as well,
> 
> I  would love to hear how.

You're right: You can't.  :-(  I was remembering older versions and
intentions.  There was an intention to implement this using the new
dspec system.  There's even a internal handler that knows how to
replace SUBFUNCTIONs, but the tracer and the encapsulation system do
not make use of it since LW 4.0.  It was hooked up in LW 3, but
broken, at least in LW 3.2.2.  I guess it worked once upon a time, but
now it's been broken for at least six years, and nobody's even
noticed.

If you could, it'd be in the usual way: through the Trace submenu in
the GUI or (TRACE (SUBFUNCTION BAR FOO)).
-- 
Pekka P. Pirinen
The gap between theory and practice is bigger in practice than in theory.
From: Kent M Pitman
Subject: Re: What's the point of flet?
Date: 
Message-ID: <sfwhes6frmu.fsf@world.std.com>
···············@globalgraphics.com (Pekka P. Pirinen) writes:

> "Coby Beck" <·····@mercury.bc.ca> writes:
> > "Pekka P. Pirinen" <···············@globalgraphics.com> wrote in message
> > ··················@globalgraphics.com...
> > > Erik Naggum
> > > >   You can trace inner functions [...]
> > >
> > > In LW, you can trace them as well,
> > 
> > I  would love to hear how.
> 
> You're right: You can't.  :-(  I was remembering older versions and
> intentions.  There was an intention to implement this using the new
> dspec system.  There's even a internal handler that knows how to
> replace SUBFUNCTIONs, but the tracer and the encapsulation system do
> not make use of it since LW 4.0.  It was hooked up in LW 3, but
> broken, at least in LW 3.2.2.  I guess it worked once upon a time, but
> now it's been broken for at least six years, and nobody's even
> noticed.
> 
> If you could, it'd be in the usual way: through the Trace submenu in
> the GUI or (TRACE (SUBFUNCTION BAR FOO)).

I think at minimum every implementation should try to support the following.
Note that STEP, for example, is required to work on lexical entities.  I
think it makes sense for TRACE to as well.

(defun foo (x)
 (labels ((foo1 (x n)
            (if (zerop x) 
                n
                (foo1 (- x 1) (* x n)))))
   (trace foo1)
   (foo1 x 1)))

This, at least, does not require a facility for naming internal functions.
It reduces the problem to having an internal fsetq operation and an ability
to mark a function object encapsulated or to wrap a function object, either
of which the trace facility should already be able to do.  The compiler 
could notice the presence of a lexical call to trace and could infer both
NOTINLINE-ness and DEBUG=3-ness.
From: sal6741
Subject: Re: What's the point of flet?
Date: 
Message-ID: <3BE1A672.BE934BC9@hotmail.com>
Erik,

Your "silliness" provides a workaround for problems in my cheapware Lisp
and in-house company packages. Thanks for the post.

Erik Naggum wrote:
> 
> * Vebjorn Ljosa <·····@ljosa.com>
> | But it also makes the parts impossible to test separately.
> 
>   You may simply need a better Common Lisp environment.
> 
>   Suppose you have this silly function:
> 
> (defun foo ()
>   (flet ((bar () t))
>     (bar)))
> 
>   In Allegro CL, this defines two functions reachable with fdefinition: one
>   named by the symbol foo, and one named by the list (flet foo bar).  That
>   is, #'(flet foo bar) returns the inner function bar.  If this is not a
>   closure, it is funcallable.
> 
> (funcall #'(flet foo bar))
> => t
> 
>   You can trace inner functions and use these function names in a number of
>   interesting places.  I think this is a very useful and intelligent
>   extension to the function name concept, given that it has to be supported
>   for setf methods.
> 
> ///
> --
>   Norway is now run by a priest from the fundamentalist Christian People's
>   Party, the fifth largest party representing one eighth of the electorate.
> --
>   Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
From: Erik Naggum
Subject: Re: What's the point of flet?
Date: 
Message-ID: <3213492104079145@naggum.net>
* Drew McDermott
| The only use I can think of for it is to override the definition of an
| existing function.

  You are not allowed to do that for symbols in the COMMON-LISP package, so
  using the function car as the example is particularly ill-conceived and
  misleading, but if you have user-defined functions that you would like to
  try this on, I'm sure that would have some utility.

///
-- 
  Norway is now run by a priest from the fundamentalist Christian People's
  Party, the fifth largest party representing one eighth of the electorate.
-- 
  Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
From: Tim Bradshaw
Subject: Re: What's the point of flet?
Date: 
Message-ID: <nkj7ktct7sx.fsf@omega.tardis.ed.ac.uk>
Drew McDermott <··············@yale.edu> writes:

> Does anyone actually use flet (as opposed to labels)?

Yes.  Apart from the use for the reader of indicating that some
function is not recursive, I have actually used it to locally override
global functions, in the sense of essentially providing a local AROUND
method (except the functions I was overriding were functions, not
GFs).  I can't remember enough context now, but it seemed like a sane
design at the time.

--tim
From: Paul Foley
Subject: Re: What's the point of flet?
Date: 
Message-ID: <m2vggwlk84.fsf@mycroft.actrix.gen.nz>
On Tue, 30 Oct 2001 15:46:22 -0500, Drew McDermott wrote:

> Does anyone actually use flet (as opposed to labels)?

I always use LET and FLET unless I need LET* and LABELS.

> The only use I can think of for it is to override the definition of an
> existing function.  E.g.:

But that's illegal -- you're not allowed to redefine names exported
from the COMMON-LISP package.

-- 
The power of accurate observation is commonly called cynicism by those
who have not got it.
                                                    -- George Bernard Shaw
(setq reply-to
  (concatenate 'string "Paul Foley " "<mycroft" '(··@) "actrix.gen.nz>"))
From: Thomas F. Burdick
Subject: Re: What's the point of flet?
Date: 
Message-ID: <xcv668w8w32.fsf@hurricane.OCF.Berkeley.EDU>
Paul Foley <·······@actrix.gen.nz> writes:

> On Tue, 30 Oct 2001 15:46:22 -0500, Drew McDermott wrote:
> 
> > Does anyone actually use flet (as opposed to labels)?
> 
> I always use LET and FLET unless I need LET* and LABELS.
> 
> > The only use I can think of for it is to override the definition of an
> > existing function.  E.g.:
> 
> But that's illegal -- you're not allowed to redefine names exported
> from the COMMON-LISP package.

You're not allowed to redifine things *in* the COMMON-LISP package.
Of course, that's not to say that you wouldn't want to override the
definition of your own function.  Even one named CDR.

  [162]> (defpackage :my-package (:use :cl) (:shadow :cdr))
  #<PACKAGE MY-PACKAGE>
  [163]> (in-package :my-package)
  #<PACKAGE MY-PACKAGE>
  MY-PACKAGE[35]> (defun cdr (cons) (cl:cdr cons))
  CDR
  MY-PACKAGE[165]>
  (defmacro with-fussy-cdr (&body forms)
    `(flet ((cdr (cons)
              (if (consp cons)
                  (cdr cons)
                  (error "I'm fussy!"))))
       ,@forms))
  WITH-FUSSY-CDR
  MY-PACKAGE[166]> (macroexpand '(with-fussy-cdr (cdr '(1 . 2)) (cdr nil)))
  (FLET
   ((CDR (CONS) (IF (CONSP CONS) (CDR CONS) (ERROR "I'm fussy!"))))
   (CDR '(1 . 2)) (CDR NIL)) ;
  T
  MY-PACKAGE[167]> (with-fussy-cdr (cdr nil))
  
  *** - I'm fussy!
  1. Break MY-PACKAGE[168]> abort
  MY-PACKAGE[169]> (with-fussy-cdr (cdr '(1 . 2)))
  2

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Paul Foley
Subject: Re: What's the point of flet?
Date: 
Message-ID: <m2d734kv4z.fsf@mycroft.actrix.gen.nz>
On 30 Oct 2001 16:57:53 -0800, Thomas F Burdick wrote:

> Paul Foley <·······@actrix.gen.nz> writes:
>> On Tue, 30 Oct 2001 15:46:22 -0500, Drew McDermott wrote:
>> 
>> > Does anyone actually use flet (as opposed to labels)?
>> 
>> I always use LET and FLET unless I need LET* and LABELS.
>> 
>> > The only use I can think of for it is to override the definition of an
>> > existing function.  E.g.:
>> 
>> But that's illegal -- you're not allowed to redefine names exported
>> from the COMMON-LISP package.

> You're not allowed to redifine things *in* the COMMON-LISP package.
> Of course, that's not to say that you wouldn't want to override the
> definition of your own function.  Even one named CDR.

Yes, of course, I know that, but the OP suggested (flet ((car ...)) ) 
without any indication that CAR wasn't CL:CAR.  I suppose I should
have said "symbols" rather than "names", above, though; of course any
number of distinct symbols can exist with the same "name".

-- 
The power of accurate observation is commonly called cynicism by those
who have not got it.
                                                    -- George Bernard Shaw
(setq reply-to
  (concatenate 'string "Paul Foley " "<mycroft" '(··@) "actrix.gen.nz>"))
From: Kent M Pitman
Subject: Re: What's the point of flet?
Date: 
Message-ID: <sfwpu74hban.fsf@world.std.com>
Paul Foley <·······@actrix.gen.nz> writes:

> 
> On Tue, 30 Oct 2001 15:46:22 -0500, Drew McDermott wrote:
> 
> > Does anyone actually use flet (as opposed to labels)?
> 
> I always use LET and FLET unless I need LET* and LABELS.
> 
> > The only use I can think of for it is to override the definition of an
> > existing function.  E.g.:
> 
> But that's illegal -- you're not allowed to redefine names exported
> from the COMMON-LISP package.

Believe it or not, some functions that exist and require overriding are 
your own.

(defun square (x) (* x x))

(flet ((square (x)
         (make-instance 'square :area (square x))))
  ...)

Ok, it's contrived.  See my other post in this thread for a more
compelling example.  But it is conforming and it does override an
"existing" function.
From: Francis Leboutte
Subject: Re: What's the point of flet?
Date: 
Message-ID: <mt30utk9sppidrbss4fh9d0n52s3lipq2b@4ax.com>
Kent M Pitman <······@world.std.com> wrote:

>Paul Foley <·······@actrix.gen.nz> writes:
>
>> But that's illegal -- you're not allowed to redefine names exported
>> from the COMMON-LISP package.
>
>Believe it or not, some functions that exist and require overriding are 
>your own.
>
>(defun square (x) (* x x))
>
>(flet ((square (x)
>         (make-instance 'square :area (square x))))
>  ...)
>

It would be nice to have the possibility to make the new binding of square have
dynamic scope. I think an equivalent of the dynamic variable notion for a
function defined locally would be useful in CL.
--
www.algo.be
Logo programming : www.algo.be/logo.html
From: Coby Beck
Subject: Re: What's the point of flet?
Date: 
Message-ID: <pTVD7.569314$8c3.90333738@typhoon.tampabay.rr.com>
"Francis Leboutte" <··········@algo.be> wrote in message
·······································@4ax.com...
> Kent M Pitman <······@world.std.com> wrote:
>
> >(defun square (x) (* x x))
> >
> >(flet ((square (x)
> >         (make-instance 'square :area (square x))))
> >  ...)
> >
>
> It would be nice to have the possibility to make the new binding of square
have
> dynamic scope. I think an equivalent of the dynamic variable notion for a
> function defined locally would be useful in CL.
> --

You could simulate this fairly easily with a nice little macro.  Save the
original function object, set the function slot of your symbol to your new
lambda expression and using unwind-protect restore the original binding at the
end.

Coby
--
(remove #\space "coby . beck @ opentechgroup . com")
From: ···@itasoftware.com
Subject: Re: What's the point of flet?
Date: 
Message-ID: <vggvwy62.fsf@itasoftware.com>
"Coby Beck" <·····@mercury.bc.ca> writes:

> "Francis Leboutte" <··········@algo.be> wrote in message
> ·······································@4ax.com...
> > Kent M Pitman <······@world.std.com> wrote:
> >
> > >(defun square (x) (* x x))
> > >
> > >(flet ((square (x)
> > >         (make-instance 'square :area (square x))))
> > >  ...)
> > >
> >
> > It would be nice to have the possibility to make the new binding of square
> have
> > dynamic scope. I think an equivalent of the dynamic variable notion for a
> > function defined locally would be useful in CL.
> > --
> 
> You could simulate this fairly easily with a nice little macro.  Save the
> original function object, set the function slot of your symbol to your new
> lambda expression and using unwind-protect restore the original binding at the
> end.

Won't work under multitasking.
From: Coby Beck
Subject: Re: What's the point of flet?
Date: 
Message-ID: <mfWD7.570599$8c3.90352085@typhoon.tampabay.rr.com>
<···@itasoftware.com> wrote in message ·················@itasoftware.com...
> "Coby Beck" <·····@mercury.bc.ca> writes:
>
> > "Francis Leboutte" <··········@algo.be> wrote in message
> > ·······································@4ax.com...
> > > dynamic scope. I think an equivalent of the dynamic variable notion for a
> > > function defined locally would be useful in CL.
> > > --
> >
> > You could simulate this fairly easily with a nice little macro.  Save the
> > original function object, set the function slot of your symbol to your new
> > lambda expression and using unwind-protect restore the original binding at
the
> > end.
>
> Won't work under multitasking.
>

Most simulations fall short of the real thing...

Coby
--
(remove #\space "coby . beck @ opentechgroup . com")
From: Kent M Pitman
Subject: Re: What's the point of flet?
Date: 
Message-ID: <sfwk7xb4s4g.fsf@world.std.com>
Francis Leboutte <··········@algo.be> writes:

> Kent M Pitman <······@world.std.com> wrote:
> 
> >Paul Foley <·······@actrix.gen.nz> writes:
> >
> >> But that's illegal -- you're not allowed to redefine names exported
> >> from the COMMON-LISP package.
> >
> >Believe it or not, some functions that exist and require overriding are 
> >your own.
> >
> >(defun square (x) (* x x))
> >
> >(flet ((square (x)
> >         (make-instance 'square :area (square x))))
> >  ...)
> >
> 
> It would be nice to have the possibility to make the new binding of square have
> dynamic scope. I think an equivalent of the dynamic variable notion for a
> function defined locally would be useful in CL.

The language doesn't actually need this functionality.  It would 
mostly be abused.

In the case that someone besides yourself wrote the function you wanted
to locally clobber with dynamic-flet, you're really violating all normal
modularity ethics.  You aren't responsible for their code, you can't know
with certainty who their clients are, and you're just asking for trouble.

(It's fine for users to write it if they have to, since
then they can take moral responsibility for the consequences, but absent an
example of a legitimate use of this, I think we made the right decision
in excluding this.  In most cases where you know you need this, it suffices
to simply bind a special variable and have a function call another function
indirect through the special.)

If you really wanted to patckage it up, it would look something like this:

(eval-when (:execute :compile-toplevel :load-toplevel)

(defvar *dynamic-flet-package*
  (or (find-package "FLET INDIRECTION")
      (make-package "FLET INDIRECTION")))

(defun make-flet-indirection (symbol)
  (intern (let ((*package* (load-time-value (find-package "CL"))))
           (format nil "*DYNAMIC-FLET ~S Indirection*" symbol))
          *dynamic-flet-package*))

);nehw-lave

(defmacro make-dynamically-flettable (name)
  (let ((indirection (make-flet-indirection name)))
    `(progn
       (defvar ,indirection (symbol-function ',name))
       (defun ,name (&rest args)
         (declare (dynamic-extent args))
         (apply ,indirection args))
       ',name)))

(defmacro dynamic-flet (fbindings &body forms)
  `(let ,(mapcar #'(lambda (fbinding)
                     (destructuring-bind (op &rest lambda-exp-tail) fbinding
                       `(,(make-flet-indirection op)
                         #'(lambda ,@lambda-exp-tail))))
                 fbindings)
     ,@forms))

;; Sample use

(defun foo (x) (+ x 3))

(make-dynamically-flettable foo)

(defun bar (x) (foo x))

(bar 4) => 7

(dynamic-flet ((foo (x) (+ x 4)))
  (bar 7)) => 8

Note that there are some tricky issues here if you end up needing to 
redefine the original FOO, but if FOO is a function you yourself maintain,
such that you hae the right to be doing this operation at all, you can usually
control those cases.
From: Erik Naggum
Subject: Re: What's the point of flet?
Date: 
Message-ID: <3213555018873937@naggum.net>
* Francis Leboutte
| It would be nice to have the possibility to make the new binding of
| square have dynamic scope. I think an equivalent of the dynamic variable
| notion for a function defined locally would be useful in CL.

  There is a letf macro going around in various versions that can be used
  for this effect:

(letf (((symbol-function 'whatever) (lambda ...))) ...)

  It basically does

(let ((<gensym> (symbol-function 'whatever)))
  (setf (symbol-function 'whatever) (lambda ...))
  (unwind-protect
      ...
    (setf (symbol-function 'whatever) <gensym>)))

///
-- 
  Norway is now run by a priest from the fundamentalist Christian People's
  Party, the fifth largest party representing one eighth of the electorate.
-- 
  Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
From: Kent M Pitman
Subject: Re: What's the point of flet?
Date: 
Message-ID: <sfwd73377pu.fsf@world.std.com>
Erik Naggum <····@naggum.net> writes:

> * Francis Leboutte
> | It would be nice to have the possibility to make the new binding of
> | square have dynamic scope. I think an equivalent of the dynamic variable
> | notion for a function defined locally would be useful in CL.
> 
>   There is a letf macro going around in various versions that can be used
>   for this effect:
> 
> (letf (((symbol-function 'whatever) (lambda ...))) ...)
> 
>   It basically does
> 
> (let ((<gensym> (symbol-function 'whatever)))
>   (setf (symbol-function 'whatever) (lambda ...))
>   (unwind-protect
>       ...
>     (setf (symbol-function 'whatever) <gensym>)))
 
The Lisp Machine more correctly called this action LETF-GLOBALLY since its
"bindings" are visible to other processes and not "bound" in the same sense
that a special variable binding are.

What the Lisp Machine called LETF is the one that requires the controversial
DYNAMIC-WIND to implement, with the wind/unwind being done on every process
schedule so that other processes don't see the binding during the dynamic
term of the body's invocation.

I prefer that naming, and I wish that anyone using the UNWIND-PROTECT kludge
would use LETF-GLOBALLY as the name.

Though I don't doubt that your observation, as a strict matter of fact,
correctly describes the unfortunate thing people are doing.

The CLIM sources, last I saw, use the name LETF because they *want* the 
per-process binding.  But someone changed the implementation for non-LispM
to be what LETF-GLOBALLY does.  And, as I've mentioned before, a mess results
if you try to do multi-tasking of CLIM with the incorrectly implemented
LETF.
From: ···@itasoftware.com
Subject: Re: What's the point of flet?
Date: 
Message-ID: <n126czxc.fsf@itasoftware.com>
Kent M Pitman <······@world.std.com> writes:

> What the Lisp Machine called LETF is the one that requires the controversial
> DYNAMIC-WIND to implement, with the wind/unwind being done on every process
> schedule so that other processes don't see the binding during the dynamic
> term of the body's invocation.

The effect was the same as `dynamic wind', but it used special
forwarding pointers pushed on the SPECPDL so that the wind/unwind was
handled by the same mechanism that swapped the special bindings on a
stack group switch.

> And, as I've mentioned before, a mess results if you try to do
> multi-tasking of CLIM with the incorrectly implemented LETF.

Well, lisp just doesn't work as nicely on stock hardware.
From: Francis Leboutte
Subject: Re: What's the point of flet?
Date: 
Message-ID: <7cncut8v840lc480jhre7d4rrh9dgogb53@4ax.com>
Francis Leboutte <··········@algo.be> wrote:

>It would be nice to have the possibility to make the new binding of square have
>dynamic scope. I think an equivalent of the dynamic variable notion for a
>function defined locally would be useful in CL.

Thank you to all for the feedback and suggestions. Actually my question was
related to a problem I had to solve a few years ago. How to generate a DXF file
that corresponds to the map of an electrical network drawn by a Lisp function
(using ACL and CG - Common Graphics - DXF means Drawing Interchange Format, a
format that can be read by many drawing and GIS software)? Simply redefine some
low-level CG drawing functions (like draw-line, draw-circle, ...) to write DXF
stuff into the DXF file, during a call to the lisp function that draws the
network (thanks to a macro like the one some of you have suggested). It was
really easy (DXF apart) but would have been even more easy if a dynamic-flet was
available... BTW I'm wondering if it would be that easy in C++ and Java?
--
www.algo.be
Logo programming : www.algo.be/logo.html
From: Drew McDermott
Subject: Re: What's the point of flet?
Date: 
Message-ID: <3BE029F2.7355D32E@yale.edu>
Paul Foley wrote:But that's illegal -- you're not allowed to redefine names
exported

> from the COMMON-LISP package.
>

Gee, it works in Allegro:

(flet ((car (x)
         (cond ((consp x) (car x))
               ((stringp x) (elt x 0))
               ((integerp x)
                (do ((y x (truncate y 10))
                     (prev 0 y))
                    ((= y 0)
                     (cond ((= prev 0)
                            (error "Can't take car of 0"))
                           (t (abs prev))))))
               (t (error "Can't take car of " x)))))
  (list (car '(9 p q)) (car 98) (car "9, danke")))

=> (9 9 #\9)

I think you're not allowed to redefine car *globally*.  Local redefinitions
are visible to the compiler and so cause no confusion.

    -- Drew McDermott
From: Kent M Pitman
Subject: Re: What's the point of flet?
Date: 
Message-ID: <sfwitcv4rw6.fsf@world.std.com>
Drew McDermott <··············@yale.edu> writes:

> Paul Foley wrote:But that's illegal -- you're not allowed to redefine names
> exported
> 
> > from the COMMON-LISP package.
> >
> 
> Gee, it works in Allegro:
> 
> (flet ((car (x)
>          (cond ((consp x) (car x))
>                ((stringp x) (elt x 0))
>                ((integerp x)
>                 (do ((y x (truncate y 10))
>                      (prev 0 y))
>                     ((= y 0)
>                      (cond ((= prev 0)
>                             (error "Can't take car of 0"))
>                            (t (abs prev))))))
>                (t (error "Can't take car of " x)))))
>   (list (car '(9 p q)) (car 98) (car "9, danke")))
> 
> => (9 9 #\9)
> 
> I think you're not allowed to redefine car *globally*.  Local redefinitions
> are visible to the compiler and so cause no confusion.

Don't confuse definition with implementation.  I think Paul was
referring to the following, which explains why what you did may have
"worked" but isn't "conforming":

 11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming Programs

 Except where explicitly allowed, the consequences are undefined if any of
 the following actions are performed on an external symbol of the COMMON-LISP
 package: 

 ...
 2. Defining, undefining, or binding it as a function. (Some exceptions 
 are noted below.) 
 ...
From: Erik Naggum
Subject: Re: What's the point of flet?
Date: 
Message-ID: <3213571753334152@naggum.net>
* Drew McDermott
| Gee, it works in Allegro:

  Gee, if you are told by your lawmakers not to do something, do you think
  that physically blocks your ability to do it, or do you think it is an
  appeal to your ethics to block your desire to do it?  If you do something
  that you are not allowed to do and it "works", are you concerned that you
  are no longer safe from unwanted side-effects of doing something wrong,
  which you would be safe from if you only did stuff you were allowed to
  do, or do you not give a damn about such consequences?

  Some people have to be punished harhsly to understand that they should
  refrain from doing something that others have decided is wrong.  Maybe
  "understand" is too strong -- I do not think it gets further than being
  scared of the consequences and thus only refrain from doing it without
  actually getting the idea.  Lacking electrical shocks from the compiler
  to the stupid programmer, we rely on actual understanding.  This will
  fail a significant fraction of the time, unfortunately, and the more
  people who think that feeding wrong code to a compiler and getting
  something useful back means it must be OK, the more problems the vendors
  have when the want to change important things in their code, and thus the
  whole user community is left in a serious bind if people who are not able
  to grasp the difference between right and wrong also blame the vendor if
  their bad code breaks in a new version.

| I think you're not allowed to redefine car *globally*.

  It does not matter what you think.  Consult the standard.  The section
  you want to study is 11.1.2.1.2, but the whole thing should be read.
  Ignorance of the standard is no excuse.

///
-- 
  Norway is now run by a priest from the fundamentalist Christian People's
  Party, the fifth largest party representing one eighth of the electorate.
-- 
  Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.