From: Mike Engber
Subject: nested function definitions
Date: 
Message-ID: <5862@spool.cs.wisc.edu>
What does nesting function definition do in Common Lisp? For example:

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

I saw this style of coding in an article. I played around with it using
Allegro Common Lisp (on a Mac) and it seems to create some sort of closure.
It also seems to me that this is a more inefficient way to do "PASCAL"
style nesting than using FLET. Does anyone what this nesting really does?

-ME

From: Sandra J Loosemore
Subject: Re: nested function definitions
Date: 
Message-ID: <5568@utah-cs.UUCP>
In article <····@spool.cs.wisc.edu>, ······@speedy.cs.wisc.edu (Mike Engber) writes:
> What does nesting function definition do in Common Lisp? For example:
> 
> (defun cube (x)
>  (defun square (x)
>   (* x x))
>  (* x (square x)))
> 
> I saw this style of coding in an article. I played around with it using
> Allegro Common Lisp (on a Mac) and it seems to create some sort of closure.
> It also seems to me that this is a more inefficient way to do "PASCAL"
> style nesting than using FLET. Does anyone what this nesting really does?

Strictly speaking, Common Lisp does not (yet) support DEFUN except at
"top-level" locations; see CLtL p. 66.  However, there is currently a
proposal before X3J13 (the ANSI Common Lisp standardization committee)
to clarify and extend the language on this point.  Under this proposal,
DEFUN would always set the *global* function definition of the symbol
(unlike FLET, which establishes a lexical function binding).

In your example above, the symbol-function of SQUARE would be setf'ed
each time CUBE is entered.  Since no variables that are closed over are
referenced inside the body of SQUARE, the function would not necessarily
have to be represented as a closure.  Note that the functional binding
of SQUARE persists after CUBE has been exited.

-Sandra Loosemore (······@cs.utah.edu)
From: Barry Margolin
Subject: Re: nested function definitions
Date: 
Message-ID: <22427@think.UUCP>
In article <····@ubc-cs.UUCP> ·····@faculty.cs.ubc.ca (Vincent Manis) writes:
>I think it's a mistake to define an internal definition to change the
>*global* value of the function cell: this is almost always not what
>one would expect, given lexical binding. Either don't provide it at
>all (as CL doesn't) or give it the same semantics as in Scheme. 

Why is it any wronger for DEFUN to change the global value than it is
for SETQ?  The way I think of it, DEFUN is to FLET/LABELS as SETQ is
to LET.

This does bring up a good question for the X3J13 compiler subcommittee
to consider.  What does:

(defun foo (x)
  (flet ((internal (y)
	   (+ x y)))
    (defun internal (y)
      (* x y))
    (internal 3)))

do?  If my analogy is completely correct, this shouldn't have any
effect on INTERNAL's global function cell.

From what I remember at the X3J13 meeting, I think my analogy is
incorrect.  I think the analogy that the compiler subcommittee is
using is DEFUN is to FLET as (SETF SYMBOL-VALUE) is to FLET, i.e.
(DEFUN name ...) macroexpands into (SETF (SYMBOL-FUNCTION 'name)
#'(LAMBDA ...)) plus some unspecified implementation-specific stuff.

Barry Margolin
Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar
From: Sandra J Loosemore
Subject: Re: nested function definitions
Date: 
Message-ID: <5570@utah-cs.UUCP>
In article <·····@think.UUCP>, ······@think.COM (Barry Margolin) writes:
> I think the analogy that the compiler subcommittee is
> using is DEFUN is to FLET as (SETF SYMBOL-VALUE) is to FLET, i.e.
> (DEFUN name ...) macroexpands into (SETF (SYMBOL-FUNCTION 'name)
> #'(LAMBDA ...)) plus some unspecified implementation-specific stuff.

Yes, that is essentially correct, except I think you really meant to
say LET instead of FLET at the end of the second line.

If you wanted a DEFUN inside an FLET or LABELS to be able to redefine a
local function, you'd either have to make it a special form or define
a new special form for it to expand into.  The problem is that Common
Lisp doesn't provide anything analagous to SETQ that can magically
modify either a lexical function binding or a global function binding,
depending on the context in which it appears.  Personally, I think
Common Lisp has quite enough special forms already, and I'm not
convinced that such a "feature" would be particularly useful anyway.

-Sandra
From: Vincent Manis
Subject: Re: nested function definitions
Date: 
Message-ID: <3266@ubc-cs.UUCP>
Barry Margolin asks why I think DEFUN should be local if SETQ can be
global. Basically, DEFUN performs an act of *binding*, whereas SETQ
does an *assignment*.  A function or value cell need not exist prior
to DEFUN (or any other DEF form), whereas such a cell must exist prior
to SETQ.

Because of this difference, I see DEFUN as a lot closer to LET than it
is to SETQ. Since LET is lexically scoped, so too should DEFUN.



Vincent Manis                    | ·····@cs.ubc.ca
The Invisible City of Kitezh     | ·····@cs.ubc.cdn
Department of Computer Science   | ·····@ubc.csnet
University of British Columbia   | uunet!ubc-cs!manis
<<NOTE NEW ADDRESS>>             |      
From: Barry Margolin
Subject: Re: nested function definitions
Date: 
Message-ID: <22683@think.UUCP>
In article <····@ubc-cs.UUCP> ·····@faculty.cs.ubc.ca (Vincent Manis) writes:
>Barry Margolin asks why I think DEFUN should be local if SETQ can be
>global. Basically, DEFUN performs an act of *binding*, whereas SETQ
>does an *assignment*.  A function or value cell need not exist prior
>to DEFUN (or any other DEF form), whereas such a cell must exist prior
>to SETQ.

Since when?  I can do (SETQ *FOO* 3) anyplace where (DEFUN FOO ...) is
permitted.  While it may be bad style to do this without first doing
(DEFVAR *FOO*), I don't think it is invalid.

>Because of this difference, I see DEFUN as a lot closer to LET than it
>is to SETQ. Since LET is lexically scoped, so too should DEFUN.

There is absolutely no precedent for this.  All the special forms that
instantiate a lexically-scoped name do so only within the body of that
special form.  You are proposing that in

(let (...)
  (defun foo ...)
  ...)

the scope of FOO would be the entire LET body, i.e. that the DEFUN
would affect the environment of the special form that contains it.
What about

(defun foo () (print 'outer))

(let ((bar nil))
  (setq bar #'(lambda () (foo)))
  (funcall bar)
  (defun foo () (print 'inner))
  (funcall bar))

Does this print OUTER followed by INNER, INNER twice, or does it get
an error?  I can think of justifications for all of these behaviors.

FLET and LABELS already exist for defining functions that can only be
accessed within a lexical scope.  What additional function does your
lexical DEFUN provide?


Barry Margolin
Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar
From: James Caldwell
Subject: Re: nested function definitions
Date: 
Message-ID: <11314@steinmetz.ge.com>
In article <····@utah-cs.UUCP> ······@utah-cs.UUCP (Sandra J Loosemore) writes:
>In article <····@spool.cs.wisc.edu>, ······@speedy.cs.wisc.edu (Mike Engber) writes:
>> What does nesting function definition do in Common Lisp? For example: ...
>
>Strictly speaking, Common Lisp does not (yet) support DEFUN except at
>"top-level" locations; see CLtL p. 66.  ...
>
Steele leaves it open, see CLtL p. 67, where he describes what
the proper lexical environment should be for a defun form that does
not appear at the top-level.

In their interpreters, Lucid and Franz both correctly handle the case

(let ((x 1))
  (defun y () x))

returning 1 when y is called.  Unfortunately they complain if you try
to compile y since y's lexical environment is not empty.  Nesting 
defuns within the scope of a let is very useful for defining variables
and functions that are global to a couple of named functions.  This
technique is used a number of times in Charniak, Riesbeck, McDermott
and Meehan's book _Artifical_Intelligence_Programming_.   

Of course the same effect can be had by collecting those couple of
functions into their own package, defvaring the variables and defuning
the functions and then exporting only the desired named functions.  A
lexical closure is a simpler and more elegant mechanism and avoids a
proliferation of packages.

>... there is currently a proposal before X3J13 ...  Under this
>proposal, DEFUN would always set the *global* function definition of
>the symbol ... 

I assume the proposal is intended to allow named functions to be
defined with a non-empty lexical environment.  Sounds good to me.

>-Sandra Loosemore (······@cs.utah.edu)

  Jim Caldwell     ··················@steinmetz.UUCP
                   uunet!steinmetz!akhenaten!caldwell

  Jim Caldwell     ··················@steinmetz.UUCP
                   uunet!steinmetz!akhenaten!caldwell
From: Jeff Dalton
Subject: Re: nested function definitions
Date: 
Message-ID: <483@aiva.ed.ac.uk>
In article <····@utah-cs.UUCP> ······@utah-cs.UUCP (Sandra J Loosemore) writes:
>Strictly speaking, Common Lisp does not (yet) support DEFUN except at
>"top-level" locations; see CLtL p. 66.

I disagree with this interpretation of CLtL.  Page 67 is clearly and
explicitly defined the meaning of DEFUN when not at the top-level.
Page 66 is relatively vague, but the only thing it definately says
may not work is the compilation of such DEFUNs.  That is why, after
all, this issue has been sent to x3j13's compilewr committee.

Jeff Dalton,                      JANET: ········@uk.ac.ed             
AI Applications Institute,        ARPA:  ·················@nss.cs.ucl.ac.uk
Edinburgh University.             UUCP:  ...!ukc!ed.ac.uk!J.Dalton
From: Barry Margolin
Subject: Re: nested function definitions
Date: 
Message-ID: <22394@think.UUCP>
In article <····@spool.cs.wisc.edu> ······@speedy.cs.wisc.edu (Mike Engber) writes:
>What does nesting function definition do in Common Lisp? For example:
>
>(defun cube (x)
> (defun square (x)
>  (* x x))
> (* x (square x)))

Sandra gave an answer about the above definition, and described a
proposal that is currently being considered by the standardization
committee.  The above example, however, doesn't show off the more
interesting aspects of the proposed extension to the language, because
it shadows parameter variables, so no variables get closed over.
Consider instead:

(defun weirdo (x)
  (defun weirdo-internal (y)
    (+ x y))
  (weirdo-internal (sqrt x)))

What does (weirdo 4) do?  It actually has what I think of as a
first-order behavior and a second-order behavior.  The first-order
behavior is that it returns 6 (it computes (+ 4 (sqrt 4))).  However,
as Sandra pointed out, it also sets the global function binding of the
WEIRDO-INTERNAL symbol; this is the second-order behavior.  If you
were to then do (weirdo-internal 10), the returned value would be 14,
because WEIRDO-INTERNAL's function binding is a closure over the value
of X as of the last time WEIRDO was called.  If you then do (weirdo
9), it will return 12, and the next (weirdo-internal 10) will return
19.

Barry Margolin
Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar