From: Dr. Bernat
Subject: Compiling lexical closures
Date: 
Message-ID: <304@utep-vaxa.UUCP>
I am trying to compile a lexical closure in Franz Common LISP and
keeping getting the "illegal function form" message.  It seems to
me that I should be able to compile closures.

For example,
(defun test (a) (function (lambda (x) (cons x a))))
(test 5) => returns a lexical closure
(funcall (test 5) 6) => (6.5) as expected
but
(compile nil (test 5)) gives the error message

Can anyone help?

Thanks,
Andrew Bernat
CS Dept.
U.Texas @ El Paso
UUCP ...ut-sally!utep-vaxa!bernat
BITNET ····@UTEP
915/747-5470

From: Chris McConnell
Subject: Re: Compiling lexical closures
Date: 
Message-ID: <3704@zodiac.UUCP>
To get a compiled closure, you want to compile the function that
generates the closure, not the closure itself.  So, in your example:

(compile 'test)
#<test number>
(test 5)
#<(:internal test 0) number>
From: Charles A. Cox
Subject: Re: Compiling lexical closures
Date: 
Message-ID: <23878@ucbvax.BERKELEY.EDU>
In article <···@utep-vaxa.UUCP> ······@utep-vaxa.UUCP (Dr. Bernat ) writes:
>I am trying to compile a lexical closure in Franz Common LISP and
>keeping getting the "illegal function form" message.  It seems to
>me that I should be able to compile closures.

Page 438 of CLtL:

   compile name &optional definition         [function]

   If definition is supplied, it should be a
   lambda-expression, the interpreted function to be
   compiled.  If not supplied, then name should be a symbol
   with a definition that is a lambda-expression.
   [...]

If you want compiled closures, the correct thing to do is to compile
the function which creates the closures, as this will cause all
closures created to be compiled.
From: David A Duff
Subject: Re: Compiling lexical closures
Date: 
Message-ID: <10734@steinmetz.ge.com>
In article <·····@ucbvax.BERKELEY.EDU> ···@renoir.Berkeley.EDU.UUCP (Charles A. Cox) writes:
>In article <···@utep-vaxa.UUCP> ······@utep-vaxa.UUCP (Dr. Bernat ) writes:
>>I am trying to compile a lexical closure in Franz Common LISP ...

>   [...]
>
>If you want compiled closures, the correct thing to do is to compile
>the function which creates the closures, as this will cause all
>closures created to be compiled.

FYI: 

In lucid common lisp, compiling the function that generates the closure will,
indeed, cause the function to generate a compiled closure.  Also, if you try
to just compile a closure by itself e.g. (compile nil (return-a-closure)), you
get the following message:

(compile nil (return-a-closure))
#<Interpreted-Function (LAMBDA (X) (PRINT X)) 7E26F7> has a non-empty lexical environment.
References to this environment will not be compiled correctly.
Do you wish to try compiling #<Interpreted-Function (LAMBDA (X) (PRINT X)) 7E26F7> anyway? (Y or N): y

#<Compiled-Function 7E3357>

Offhand, I can't see any reason why a compile shouldn't be able to do this
correctly, since the closure obviously must have a pointer to the the
environment that was in effect at the time that it was created.  I assume that
it was just a special case that the implementors chose to ignore.

Dave Duff       
GE Research and Development Center
Schenectady, New York   518-387-5649

Note: in case default return address doesn't work try one of:
·····@ge-crd.ARPA                 uunet!steinmetz!eraserhead!duff
From: Dan Hoey
Subject: Re: Compiling lexical closures
Date: 
Message-ID: <51@etl.ARPA>
In article <·····@steinmetz.ge.com> ····@eraserhead.UUCP (David A Duff) writes:
...
>In lucid common lisp, compiling the function that generates the closure will,
>indeed, cause the function to generate a compiled closure.  Also, if you try
>to just compile a closure by itself e.g. (compile nil (return-a-closure)), you
>get the following message:
>...References to this environment will not be compiled correctly....
>Offhand, I can't see any reason why a compile shouldn't be able to do this
>correctly, since the closure obviously must have a pointer to the the
>environment that was in effect at the time that it was created.  I assume that
>it was just a special case that the implementors chose to ignore.

I think the key here is that the format of the environment for an interpreted
closure doesn't have to be the same as the format of the environment for a
compiled closure.  This works because in its usual operation, the compiler
compiles the environment for each bit of code it compiles.  So the job of an
implementor to deal with the special case would be to either

1) Convert the interpreter environment to a compiler environment on entry, and
    restore any changes on exit, or

2) Emit compiled code that can manage references to an interpreter environment.

Either choice would be a lot of work to implement a feature not required by
the Common Lisp specification.  The runtime overhead for choice 1 might well
exceed the gains made by compiling.  Choice 2 might require sweeping changes
throughout the code generator.

With the costs in mind, it is a lot easier to understand why ignoring this case
is a good idea.

Dan