I suppose I'll get crucified (yet again) on syntax to
improve the language...
Macrolet and flet are very useful,
but I find the syntax is an excessive burden.
I suggest they can just be defined by embedded definition
at the beginning of a code body. Seems to me a simple
transformation in which similiar processing is already
done to handle type declarations.
-Kelly Murray ···@intellimarket.com
(function foo (x y)
(macro stroke (s) ...)
(function length (s) ...)
...
(stroke (length 10))
)
As compared with the code below, which is difficult
to convert from having local defs to not having them,
as well as adding and deleting individual defs.
(defun foo (x y)
(macrolet (
(stroke (s) ...)
)
(flet (
(length (s) ...)
)
...
(stroke (length 10))
)
)
)
In article <·················@IntelliMarket.Com>,
Kelly Murray <···@IntelliMarket.Com> wrote:
>I suppose I'll get crucified (yet again) on syntax to
>improve the language...
>
>Macrolet and flet are very useful,
>but I find the syntax is an excessive burden.
>I suggest they can just be defined by embedded definition
>at the beginning of a code body. Seems to me a simple
>transformation in which similiar processing is already
>done to handle type declarations.
One difference is that type declarations don't introduce new bindings. If
things were done "right" type declarations would actually be part of the
syntax of the variable specification in a LET form, rather than being
shoved down into the beginning of the body (see how Dylan does it, for
example).
On the other hand, Scheme has something like what you're suggesting.
"define" forms at the beginning of a function body are transformed into a
"letrec" form surrounding the body. So there certainly is precedent in the
Lisp family for this type of syntax. However, I think many Schemers
consider that syntax a wart in the language. My suspicion is that it's
there to provide a way to elide the "lambda", i.e.
(define (foo ...)
(letrec ((inner
(lambda (...)
...)))
...)) =>
(define (foo ...)
(define (inner ...)
...)
...)
It saves both a level of indentation *and* a lambda.
--
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Don't bother cc'ing followups to me.
From: Dorai Sitaram
Subject: Re: Local definitions without excessive syntax ?
Date:
Message-ID: <79t3ll$ph3$1@news.gte.com>
In article <····················@burlma1-snr1.gtei.net>,
Barry Margolin <······@bbnplanet.com> wrote:
>
>On the other hand, Scheme has something like what you're suggesting.
>"define" forms at the beginning of a function body are transformed into a
>"letrec" form surrounding the body. So there certainly is precedent in the
>Lisp family for this type of syntax. However, I think many Schemers
>consider that syntax a wart in the language. My suspicion is that it's
>there to provide a way to elide the "lambda", i.e.
>
>(define (foo ...)
> (letrec ((inner
> (lambda (...)
> ...)))
> ...)) =>
>
>(define (foo ...)
> (define (inner ...)
> ...)
> ...)
>
>It saves both a level of indentation *and* a lambda.
There is a rationalization for this wart, but I don't
know if it is aggressively voiced. To wit, both the
top-level and the internal DEFINE can be viewed as
mutating the current top-most frame of the environment,
without pushing on a new frame. The LETREC, on the
other hand, adds a brand new frame of bindings, which
can be popped off. E.g., in
(define (foo ...)
(letrec ((inner (lambda ...)))
...))
one could in theory insert code between the last two
right-parens that is still within FOO but won't see
INNER. This wouldn't be possible if we'd used
(define (foo ...)
(define (inner ...) ...)
...)
I believe people are unwilling to retire the internal
DEFINE because its presence (even if its use is
avoided) gives a consistent meaning to DEFINE. Making
DEFINE top-level only would make DEFINE too special.
And Schemers hate special (!). Besides, there is a
possibility that an eventual module or first-class
environment system might make the notion of an
exclusively top-level DEFINE untenable. Every DEFINE
would then be an internal DEFINE.
--d
From: ··········@scientia.com
Subject: Re: Local definitions without excessive syntax ?
Date:
Message-ID: <79um8h$phh$1@nnrp1.dejanews.com>
In article <·················@IntelliMarket.Com>,
Kelly Murray <···@IntelliMarket.Com> wrote:
> I suppose I'll get crucified (yet again) on syntax to
> improve the language...
>
> Macrolet and flet are very useful,
> but I find the syntax is an excessive burden.
> I suggest they can just be defined by embedded definition
> at the beginning of a code body. Seems to me a simple
> transformation in which similiar processing is already
> done to handle type declarations.
>
> -Kelly Murray ···@intellimarket.com
>
> (function foo (x y)
> (macro stroke (s) ...)
> (function length (s) ...)
> ...
> (stroke (length 10))
> )
>
> As compared with the code below, which is difficult
> to convert from having local defs to not having them,
> as well as adding and deleting individual defs.
>
> (defun foo (x y)
> (macrolet (
> (stroke (s) ...)
> )
> (flet (
> (length (s) ...)
> )
> ...
> (stroke (length 10))
> )
> )
> )
>
You could write a macro, say local-definitions, such that you could
do something like:
(defun foo (x y)
(local-definitions
((macro stroke (s) ...)
(function length (s) ...)
(variable z ...)
....)
...
(stroke (length 10))))
which then expanded into the corresponding macrolet/flet/let forms
This isn't quite what you asked for, but goes at least part of the way.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
··········@scientia.com writes:
> > -Kelly Murray ···@intellimarket.com
> >
> > (function foo (x y)
> > (macro stroke (s) ...)
> > (function length (s) ...)
> > ...
> > (stroke (length 10))
> > )
> >
> > As compared with the code below, which is difficult
> > to convert from having local defs to not having them,
> > as well as adding and deleting individual defs.
> >
> > (defun foo (x y)
> > (macrolet (
> > (stroke (s) ...)
> > )
> > (flet (
> > (length (s) ...)
> > )
> > ...
> > (stroke (length 10))
> > )
> > )
> > )
> >
>
> You could write a macro, say local-definitions, such that you could
> do something like:
>
> (defun foo (x y)
> (local-definitions
> ((macro stroke (s) ...)
> (function length (s) ...)
> (variable z ...)
> ....)
> ...
> (stroke (length 10))))
>
> which then expanded into the corresponding macrolet/flet/let forms
This is equivalent to the request of interspersed 'variable
declarations' which was made on CLL some time ago.
The easy part is to provide a WITH- form that does the one level down
parsing and rewriting. (I wrote the VARDEF package just for the heck
of it).
However, to do the "right" (quotes necessary) you need a code walker
Cheers
--
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 10 03 17, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it
Marco Antoniotti wrote:
>
> ··········@scientia.com writes:
>
> > ...
> > You could write a macro, say local-definitions, such that you could
> > do something like:
> >
> > (defun foo (x y)
> > (local-definitions
> > ((macro stroke (s) ...)
> > (function length (s) ...)
> > (variable z ...)
> > ....)
> > ...
> > (stroke (length 10))))
> >
> > which then expanded into the corresponding macrolet/flet/let forms
>
> This is equivalent to the request of interspersed 'variable
> declarations' which was made on CLL some time ago.
>
> The easy part is to provide a WITH- form that does the one level down
> parsing and rewriting. (I wrote the VARDEF package just for the heck
> of it).
>
> However, to do the "right" (quotes necessary) you need a code walker
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(Probably a dumb question) Why do you need a code walker?
Thanks, Chris
From: Tom Breton
Subject: Re: Local definitions without excessive syntax ?
Date:
Message-ID: <m3aeykfci6.fsf@world.std.com>
Chris Reedy <······@mitretek.org> writes:
> Marco Antoniotti wrote:
> >
> > ··········@scientia.com writes:
> >
> >
> > This is equivalent to the request of interspersed 'variable
> > declarations' which was made on CLL some time ago.
Which I posted on gnu.emacs.sources, since people seem to have
forgotten about it. I use it regularly, and it is the handiest thing.
I'm glad I wrote it, and will repost it if you can't find it.
> >
> > However, to do the "right" (quotes necessary) you need a code walker
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> (Probably a dumb question) Why do you need a code walker?
Because he wants to manage not just second-level structures but
nth-level structures.
--
Tom Breton, http://world.std.com/~tob
Ugh-free Spelling (no "gh") http://world.std.com/~tob/ugh-free.html
Tom Breton <···@world.std.com> writes:
> Chris Reedy <······@mitretek.org> writes:
>
> > Marco Antoniotti wrote:
> > >
> > > ··········@scientia.com writes:
> > >
> > >
> > > This is equivalent to the request of interspersed 'variable
> > > declarations' which was made on CLL some time ago.
>
> Which I posted on gnu.emacs.sources, since people seem to have
> forgotten about it. I use it regularly, and it is the handiest thing.
> I'm glad I wrote it, and will repost it if you can't find it.
>
> > >
> > > However, to do the "right" (quotes necessary) you need a code walker
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >
> > (Probably a dumb question) Why do you need a code walker?
>
> Because he wants to manage not just second-level structures but
> nth-level structures.
>
Exactly.
(define-function foo (x)
(let ((y (f x)))
(define-function bar (z) (+ x y))
#'bar))
I believe Scheme gets it right. Extending CL with a code walker is
trivial.
Cheers
--
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 10 03 17, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it
Introducing new variables without an embedded syntax is similiar,
but in terms of syntax I think there is a significant difference
between the two, because macros/functions have parens as
part of their definition already, and one tends to introduce
many variables as in (NiCLOS syntax:)
(let x = 10
y = 20
z = 30
do
..)
However, I can see how it would make sense, even if it does
add more paren to the variable declarations:
(function foo (x)
(var x 10) ;; local bindings
(var y 20)
(var z 30)
(function zap (s)(+ s 1)) ;; local function zap
;; start of actually executable code
(zap y)
)
I think the problem is that one really also needs another
single-expression syntax for embedded use, so it makes
the syntax inconsistent and thus harder to understand the code.
(function foo (x)
(var x 10) ;; local bindings
(function zap (s)(+ s 1)) ;; local function zap
;; start of actually executable code
(if (> x 10)
(progn ;; progn is just a replacement for let
(var x (- x 10)) ;; bind locally
(zap x))
)
Local variable/functions are rarely used much in an
embedded context, so this type of problem wouldn't be common.
But in any case, I then rethink my suggestion,
and revise it so function/macro definitions do use embeddings,
but change the syntax to be less cumbersome, similiar
to what Paul Rudin suggested:
I believe this is much cleaner and easier to understand
and is more consistent with my other syntax.
(function foo (x)
(flet
(function zap (s) (+ s 1))
(macro zip (s) `(zap (- ,s 1)))
do ;; clear start-code indication
(zap y)
)
)
-Kelly Murray ···@niclos.com (notice new domain ;)
Tom Breton wrote:
>
> Chris Reedy <······@mitretek.org> writes:
>
> > Marco Antoniotti wrote:
> > >
> > > ··········@scientia.com writes:
> > >
> > >
> > > This is equivalent to the request of interspersed 'variable
> > > declarations' which was made on CLL some time ago.
>
> Which I posted on gnu.emacs.sources, since people seem to have
> forgotten about it. I use it regularly, and it is the handiest thing.
> I'm glad I wrote it, and will repost it if you can't find it.
>
> > >
> > > However, to do the "right" (quotes necessary) you need a code walker
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >
> > (Probably a dumb question) Why do you need a code walker?
>
> Because he wants to manage not just second-level structures but
> nth-level structures.
>
> --
> Tom Breton, http://world.std.com/~tob
> Ugh-free Spelling (no "gh") http://world.std.com/~tob/ugh-free.html
··········@scientia.com writes:
>
> You could write a macro, say local-definitions, such that you could
> do something like:
>
> (defun foo (x y)
> (local-definitions
> ((macro stroke (s) ...)
> (function length (s) ...)
> (variable z ...)
> ....)
> ...
> (stroke (length 10))))
>
> which then expanded into the corresponding macrolet/flet/let forms
>
> This isn't quite what you asked for, but goes at least part of the way.
>
And if you've got this you could then do another macro, say
defun-with-locals, so that you could write
(defun-with-locals foo (x y)
(macro stroke (s) ...)
(function length (s) ...)
...
(stroke (length 10))
)
with expands to the corresponding defun and local-definitions forms,
which gets you nearly all the way.
From: Kent M Pitman
Subject: Re: Local definitions without excessive syntax ?
Date:
Message-ID: <sfwn22icoho.fsf@world.std.com>
I've been following this a bit, but only spot-checking. Not following
detailed discussiones. Apologies in advance if I repeat something someone
has said...
I don't have a problem with people discussing this, and it's interesting
to see what people have as wishes, but you're all using such simple examples
that they don't address the full scope of things.
I've said over and over that design features are not "good" or "bad"
but "good in a context" or "bad in a context", so to fairly evaluate
(and possibly repair) CL's local definitions, you have to first acknowledge
the full space of issues that CL is trying to deal with. Saying you only
use a couple of parts of the language and so a simple analysis suffices
doesn't really attack the whole problem.
Here are some additional things to puzzle over that may, if not make
you happy to use MACROLET and FLET, at least help you understand why
they were probably chosen over top-level DEFMACRO in a form:
[1] (defun foo (x) (+ x 1))
(defun bar (&optional (x (foo x)))
(defun foo (x) (- x 1))
(foo x))
Sure, you could define this either way--with the initform's FOO
using either the outer FOO or the inner FOO, but I can just
about guarantee you that we'd be answering questions here on
comp.lang.lisp about the scoping rules, just as we do about
declaration scope.
A variation on this problem is
(defun bar (&optional (x (foo x)))
(progn (defun foo (x) (- x 1)))
(foo x))
which is important for abstraction purposes since at top-level,
PROGN doesn't destroy top-level-ness, and you'd want a defining
macro to expand into a context.
[2] (defun setup-adder (x)
(defun adder (n) (+ n x)))
This function would become harder to write. Yes, you could change
it to
(defun setup-adder (x)
(setf (symbol-function 'adder) #'(lambda (n) (+ n x))))
but that would force people to have a lot larger repertoire about
the various parts of the language.
[3] Already many people do
(LET ((X 3))
(DEFUN F () X)
(DEFUN NEW-F () (INCF X)))
to hide use of special variables. To keep this working, you have
to either define that this is not the same as
((LAMBDA (X)
(DEFUN F () X)
(DEFUN NEW-F () (INCF X)))
3)
or that this lambda combination is not the same as
(DEFUN SETUP-F (X)
(DEFUN F () X)
(DEFUN NEW-F () (INCF X)))
(SETUP-F 3)
Right now, people assume those three renditions are all the same.
(Oops. Sorry abou thte uppercase, I did that by accident. Well,
not tha sorry. I often program in uppercase, but today I'm not
going to downcase it because it's probably good to sometimes be on
the record that some of us like uppercase just for no other reason
than that we like it. I feel like a closeted minority always in
danger of extinction.)
I think these cases make me comfortable that while indentation
is sad, it's not as sad as those questions up there. People rarely
ask what the scope of FOO is in
(defun bar (&optional (x (foo x)))
(flet ((foo (x) (- x 1)))
(foo x)))
nor in
(flet ((foo (x) (- x 1)))
(defun bar (&optional (x (foo x)))
(foo x)))
because it's explicit. A few people DO come in with the "BASIC bug"
of thinking LET is an assignment statement and wanting to write
(LET ((X 3)))
in order to assign X. But that bug is more easily fixed than [1].
Incidentally, [3] is really a combination of the problems I cited
in [1] and [2] because [1] is isomorphic to the problems we already
have with declarations (which some have leaned toward fixing with
more "binding forms", not less) and [2] is just a simpler form of [3]
where you don't plan to do the setup more than once so you didn't
name the function. But the reason I mention it is that in [1] we also
had a historical problem that we were forced by the declaration model
we chose to break an age-old tradition of LET and LAMBDA having the
comfortable relationship see in [3]. In Maclisp, LET could literally
be defined by the following (at least, it could toward the end of the
maclisp era when backquote, sharpsign, and defmacro finally made it into
the language after years of being user-defined extras):
(defmacro let (bindings &body forms)
`((lambda ,(mapcar #'car bindings) ,@forms)
,@(mapcar #'cadr bindings)))
But in CLTL1, this didn't work because the scoping rules of declarations
were such that you had to parse the FORMS argument for declarations, and
some of those declarations belonged in the body of the lambda while
others belonged in the evaluation of the arguments. (It was statistically
a better guess to that all declarations were better off being replicated
in both pieces, but I vaguely recall there was a screw case to that,
perhaps related to this goofy notion of "bound" and "free" declarations.)
Anyway, the point here is that if you introduce top-level DEFUN as a way
of "declaring" a local function, you implicitly also introduce another
confusion of this type, where when the DEFUN into which the local DEFUN
is placed is broken down into its component pieces, the mechanism to do
that gets very complicated.
Trends in Eulisp in the last decade were toward replacing CL-ish things
like
(defun f (x)
(declare (special x))
...)
with
(defun f (y)
(dynamic-let ((x y))
...))
so that it was explicit what the scope of the specialness was, I suspect
at least partly for the reasons I've cited.
All of this being said, nothing keeps anyone here from contributing a library
that has a theory of top-level-ness such that you can do DEFUN or whatever
you think belongs at top-level. I recommend that you NOT re-do the mistake
I talked the CL designers into making for CLTL1 and that was removed in CLTL2
where you macroexpand forms looking for declarations. There are two reasons
for this. First, it can easily get you into really bad performance problems
in nested situations without a strong theory of caching. That's not
very relevant here. But second, if macros can expand into setup code,
then
(defmacro define-frob (x)
`(progn (defun ,x () 'frob)
(push ',x *frobs*)
',x))
will have odd behavior if you nest it, as in:
(my-defun foo ()
(define-frob fred)
...)
where you've defined my-defun to turn body-embedded defuns into flets
by macroexpanding to find them. The problem is you'll end up with:
(defun foo ()
(flet ((fred () 'frob))
(push 'fred *frobs*)
'fred
...))
which will be a problem becuase even though you've scoped the FRED
functional definition, you've not scoped its "registration".
It's true, if the binding rules for the language were such that all
definitions did this local function hack, people might not define
frobs in that way--they might have a more complex way to do it.
Once in a while, I get namespace-happy and put all my extra functions
in FLETs and sit there proud that I've not cluttered my package's set
of symbols, but then I usually think "what point was there in that?
the package was all mine and I have nothing else to put there".
And when I look at the set of local functions that I really need, I often find
most of them (for efficiency, because I don't want to cons) can trivially
be floated out to toplevel as "loop invariants". And in the end, I mostly
don't see a lot of local functions. I use them, but rarely. And for as
often as I do, I don't mind the extra indentation.
What I DO mind is that no one ever ported the hack that made emacs
c-m-q in older editors indent things like:
(flet ((foo (x)
foobody))
fletbody)
I'm forever having to manually reindent these. But the fix is not
a fix to the language. That's a tools problem.
End of morning rant. Time to scout out some breakfast.
I only spot-checked Kent response ;) but thought I'd add what
is probably obvious about local definitions:
1) You know for certain the definition is not used elsewhere,
and thus can change it at will.
2) The definition is visibly connected where it is used,
important when editing "by form" instead of "by file".
3) It makes any function redefinition as a unit,
useful for transactional editing.
4) Creating another unneeded symbol (as another root-set entry)
is avoided
5) The compiler may optimize the call
The downside is mostly that it is harder to trace the sub-call,
which wouldn't be the case if we had source-code stepping..
Kent M Pitman wrote:
>
> I've been following this a bit, but only spot-checking. Not following
> detailed discussiones. Apologies in advance if I repeat something someone
> has said...
>
> I don't have a problem with people discussing this, and it's interesting
> to see what people have as wishes, but you're all using such simple examples
> that they don't address the full scope of things.
>
> I've said over and over that design features are not "good" or "bad"
> but "good in a context" or "bad in a context", so to fairly evaluate
> (and possibly repair) CL's local definitions, you have to first acknowledge
> the full space of issues that CL is trying to deal with. Saying you only
> use a couple of parts of the language and so a simple analysis suffices
> doesn't really attack the whole problem.
>
> Here are some additional things to puzzle over that may, if not make
> you happy to use MACROLET and FLET, at least help you understand why
> they were probably chosen over top-level DEFMACRO in a form:
>
> [1] (defun foo (x) (+ x 1))
> (defun bar (&optional (x (foo x)))
> (defun foo (x) (- x 1))
> (foo x))
>
> Sure, you could define this either way--with the initform's FOO
> using either the outer FOO or the inner FOO, but I can just
> about guarantee you that we'd be answering questions here on
> comp.lang.lisp about the scoping rules, just as we do about
> declaration scope.
>
> A variation on this problem is
> (defun bar (&optional (x (foo x)))
> (progn (defun foo (x) (- x 1)))
> (foo x))
> which is important for abstraction purposes since at top-level,
> PROGN doesn't destroy top-level-ness, and you'd want a defining
> macro to expand into a context.
>
> [2] (defun setup-adder (x)
> (defun adder (n) (+ n x)))
>
> This function would become harder to write. Yes, you could change
> it to
> (defun setup-adder (x)
> (setf (symbol-function 'adder) #'(lambda (n) (+ n x))))
> but that would force people to have a lot larger repertoire about
> the various parts of the language.
>
> [3] Already many people do
> (LET ((X 3))
> (DEFUN F () X)
> (DEFUN NEW-F () (INCF X)))
> to hide use of special variables. To keep this working, you have
> to either define that this is not the same as
> ((LAMBDA (X)
> (DEFUN F () X)
> (DEFUN NEW-F () (INCF X)))
> 3)
> or that this lambda combination is not the same as
> (DEFUN SETUP-F (X)
> (DEFUN F () X)
> (DEFUN NEW-F () (INCF X)))
> (SETUP-F 3)
> Right now, people assume those three renditions are all the same.
>
> (Oops. Sorry abou thte uppercase, I did that by accident. Well,
> not tha sorry. I often program in uppercase, but today I'm not
> going to downcase it because it's probably good to sometimes be on
> the record that some of us like uppercase just for no other reason
> than that we like it. I feel like a closeted minority always in
> danger of extinction.)
>
> I think these cases make me comfortable that while indentation
> is sad, it's not as sad as those questions up there. People rarely
> ask what the scope of FOO is in
> (defun bar (&optional (x (foo x)))
> (flet ((foo (x) (- x 1)))
> (foo x)))
> nor in
> (flet ((foo (x) (- x 1)))
> (defun bar (&optional (x (foo x)))
> (foo x)))
> because it's explicit. A few people DO come in with the "BASIC bug"
> of thinking LET is an assignment statement and wanting to write
> (LET ((X 3)))
> in order to assign X. But that bug is more easily fixed than [1].
>
> Incidentally, [3] is really a combination of the problems I cited
> in [1] and [2] because [1] is isomorphic to the problems we already
> have with declarations (which some have leaned toward fixing with
> more "binding forms", not less) and [2] is just a simpler form of [3]
> where you don't plan to do the setup more than once so you didn't
> name the function. But the reason I mention it is that in [1] we also
> had a historical problem that we were forced by the declaration model
> we chose to break an age-old tradition of LET and LAMBDA having the
> comfortable relationship see in [3]. In Maclisp, LET could literally
> be defined by the following (at least, it could toward the end of the
> maclisp era when backquote, sharpsign, and defmacro finally made it into
> the language after years of being user-defined extras):
> (defmacro let (bindings &body forms)
> `((lambda ,(mapcar #'car bindings) ,@forms)
> ,@(mapcar #'cadr bindings)))
> But in CLTL1, this didn't work because the scoping rules of declarations
> were such that you had to parse the FORMS argument for declarations, and
> some of those declarations belonged in the body of the lambda while
> others belonged in the evaluation of the arguments. (It was statistically
> a better guess to that all declarations were better off being replicated
> in both pieces, but I vaguely recall there was a screw case to that,
> perhaps related to this goofy notion of "bound" and "free" declarations.)
> Anyway, the point here is that if you introduce top-level DEFUN as a way
> of "declaring" a local function, you implicitly also introduce another
> confusion of this type, where when the DEFUN into which the local DEFUN
> is placed is broken down into its component pieces, the mechanism to do
> that gets very complicated.
>
> Trends in Eulisp in the last decade were toward replacing CL-ish things
> like
> (defun f (x)
> (declare (special x))
> ...)
> with
> (defun f (y)
> (dynamic-let ((x y))
> ...))
> so that it was explicit what the scope of the specialness was, I suspect
> at least partly for the reasons I've cited.
>
> All of this being said, nothing keeps anyone here from contributing a library
> that has a theory of top-level-ness such that you can do DEFUN or whatever
> you think belongs at top-level. I recommend that you NOT re-do the mistake
> I talked the CL designers into making for CLTL1 and that was removed in CLTL2
> where you macroexpand forms looking for declarations. There are two reasons
> for this. First, it can easily get you into really bad performance problems
> in nested situations without a strong theory of caching. That's not
> very relevant here. But second, if macros can expand into setup code,
> then
> (defmacro define-frob (x)
> `(progn (defun ,x () 'frob)
> (push ',x *frobs*)
> ',x))
> will have odd behavior if you nest it, as in:
> (my-defun foo ()
> (define-frob fred)
> ...)
> where you've defined my-defun to turn body-embedded defuns into flets
> by macroexpanding to find them. The problem is you'll end up with:
> (defun foo ()
> (flet ((fred () 'frob))
> (push 'fred *frobs*)
> 'fred
> ...))
> which will be a problem becuase even though you've scoped the FRED
> functional definition, you've not scoped its "registration".
> It's true, if the binding rules for the language were such that all
> definitions did this local function hack, people might not define
> frobs in that way--they might have a more complex way to do it.
>
> Once in a while, I get namespace-happy and put all my extra functions
> in FLETs and sit there proud that I've not cluttered my package's set
> of symbols, but then I usually think "what point was there in that?
> the package was all mine and I have nothing else to put there".
> And when I look at the set of local functions that I really need, I often find
> most of them (for efficiency, because I don't want to cons) can trivially
> be floated out to toplevel as "loop invariants". And in the end, I mostly
> don't see a lot of local functions. I use them, but rarely. And for as
> often as I do, I don't mind the extra indentation.
>
> What I DO mind is that no one ever ported the hack that made emacs
> c-m-q in older editors indent things like:
> (flet ((foo (x)
> foobody))
> fletbody)
> I'm forever having to manually reindent these. But the fix is not
> a fix to the language. That's a tools problem.
>
> End of morning rant. Time to scout out some breakfast.