Lisp HUG Maillist Archive

compile vs coerce

In Lispworks,why does

(funcall (lambda () (coerce (lambda () nil) 'function)))

run but

(funcall (lambda () (compile nil (lambda () nil))))

causes  Error: #<anonymous interpreted function 200C8D82> is a lexical closure.

The hyperspec for COMPILE says " If the definition is a lambda expression, it is coerced to a function."  I'm guessing some connection to "The consequences are undefined if the lexical environment surrounding the function to be compiled contains any bindings..." but that's not the case here, is it? I don't get the error in Allegro or SBCL.



-- 
.................................................
Christopher Riesbeck
Associate Professor, Electrical Engineering and Computer Science
McCormick School of Engineering
Northwestern University

2145 Sheridan Rd., Evanston, IL 60208

Home page: http://www.cs.northwestern.edu/~riesbeck/
Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html

Re: compile vs coerce

Christopher Riesbeck <c-riesbeck@northwestern.edu> writes:

> In Lispworks,why does
>
> (funcall (lambda () (coerce (lambda () nil) 'function)))
>
> run but
>
> (funcall (lambda () (compile nil (lambda () nil))))
>
> causes  Error: #<anonymous interpreted function 200C8D82> is a
> lexical closure.
>
> The hyperspec for COMPILE says " If the definition is a lambda
> expression, it is coerced to a function."  I'm guessing some
> connection to "The consequences are undefined if the lexical
> environment surrounding the function to be compiled contains any
> bindings..." but that's not the case here, is it? I don't get the
> error in Allegro or SBCL.

There should be no difference, and no error generated.

Are you sure lispworks generates the error you're saying, when you
evaluate either of those forms?

Try with (cl:lambda () cl:nil) 


The specification of compile is clear, the definition can be a lambda
expression or a function. In your case, it's a function (as returned by
(lambda () nil), and it doesn't matter whether it's a lexical closure,
an interpreted function or a compiled function.  Compile should return
an equivalent compiled function.

I interpret the undefined consequences about whether the returned
closure shares or not the enclosed environment:

    (let ((x 42))
         (let ((f (compile nil (lambda () x))))
           (list (funcall f)
                 (setf x 0)
                 (funcall f))))
    --> (42 0 0) 
    ;; or:
    --> (42 0 42)

One could also interpret it as saying that if you're trying to compile
a closure, then you might get an error or an invalid function, but this
would be the sign of a low-quality implementation, and that would
motivate its rejection, and definitely not worth of a commercial
implementation.

That said, CMUCL has the same failing, when the function is really a
closure:

Clozure Common Lisp            --> (42 0 0)
CLISP                          --> (42 0 0)
CMU Common Lisp                 Error in function
                                 C::GET-LAMBDA-TO-COMPILE:    
                                 #<Interpreted Function "LET ((X 42))"
                                 {581A0871}> was defined in a non-null
                                 environment.
SBCL                           --> (42 0 0)

For (lambda () nil) it compiles it as expected.

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: compile vs coerce


On 11/25/2015 12:43 PM, Pascal J. Bourguignon wrote:
> Christopher Riesbeck <c-riesbeck@northwestern.edu> writes:
>
>> In Lispworks,why does
>>
>> (funcall (lambda () (coerce (lambda () nil) 'function)))
>>
>> run but
>>
>> (funcall (lambda () (compile nil (lambda () nil))))
>>
>> causes  Error: #<anonymous interpreted function 200C8D82> is a
>> lexical closure.
> There should be no difference, and no error generated.
>
> Are you sure lispworks generates the error you're saying, when you
> evaluate either of those forms?
>
> Try with (cl:lambda () cl:nil)

Listener output, Lispworks 6 Personal Edition, nothing  loaded. Adding 
package qualifiers everywhere:

> CL-USER 5 > (cl:funcall (cl:lambda () (cl:compile cl:nil (cl:lambda () 
> cl:nil))))
>
> Error: #<anonymous interpreted function 21AF2EB2> is a lexical closure.


> The specification of compile is clear, the definition can be a lambda
> expression or a function. In your case, it's a function (as returned by
> (lambda () nil), and it doesn't matter whether it's a lexical closure,
> an interpreted function or a compiled function.  Compile should return
> an equivalent compiled function.
Being a function does seem matter here, because the following does NOT 
signal an error

> CL-USER 7 > (funcall (lambda () (compile nil '(lambda () nil))))
> #<Function 10 21CD5F22>
> NIL
> NIL

-- 
.................................................
Christopher Riesbeck
Associate Professor, Electrical Engineering and Computer Science
McCormick School of Engineering
Northwestern University

2145 Sheridan Rd., Evanston, IL 60208

Home page: http://www.cs.northwestern.edu/~riesbeck/
Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: compile vs coerce

On Wed, Nov 25, 2015 at 1:12 PM, Christopher Riesbeck
<c-riesbeck@northwestern.edu> wrote:

> (funcall (lambda () (compile nil (lambda () nil))))
>
> causes  Error: #<anonymous interpreted function 200C8D82> is a lexical
> closure.
>
> The hyperspec for COMPILE says " If the definition is a lambda expression,
> it is coerced to a function."  I'm guessing some connection to "The
> consequences are undefined if the lexical environment surrounding the
> function to be compiled contains any bindings..." but that's not the case
> here, is it? I don't get the error in Allegro or SBCL.

You're not compiling a lambda expression here, though, so that
coercion doesn't matter.  You'd have to be doing

    (compile nil '(lambda () nil))

to be compiling a lambda expression.  You're passing a closure object
as the second argument to compile. I think it's a bit strange that

! The consequences are undefined if the lexical environment
! surrounding the function to be compiled contains any bindings
! other than those for macros, symbol macros, or declarations.

would come into play here, but the evaluation of `(lambda () nil)`
would have closed over whatever the lexical environment available in
the REPL is; so maybe that's relevant?  For what it's worth, when you
actually pass a lambda expression, there's no issue:

    (funcall (lambda () (compile nil '(lambda () nil))))





>
>
>
> --
> ................................................
> Christopher Riesbeck
> Associate Professor, Electrical Engineering and Computer Science
> McCormick School of Engineering
> Northwestern University
>
> 2145 Sheridan Rd., Evanston, IL 60208
>
> Home page: http://www.cs.northwestern.edu/~riesbeck/
> Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html



-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: compile vs coerce

I've run into this sort of thing before but there were lexical
bindings in my case; I believe the problem to be that without the
quote around the inner lambda, that lambda is evaluated to produce an
interpreted function, and because it is within a lexical context (the
outer lambda) it is considered a lexical closure albeit with zero
bindings.

Because of the differences in lexical environment implementation
between compiled and interpreted contexts, the compiler throws this
error. If that's the case, perhaps LW could be improved to recognise
when the lexical environment is empty and proceed without error.

On 26 November 2015 at 06:38, Christopher Riesbeck
<c-riesbeck@northwestern.edu> wrote:
>
>
> On 11/25/2015 12:43 PM, Pascal J. Bourguignon wrote:
>>
>> Christopher Riesbeck <c-riesbeck@northwestern.edu> writes:
>>
>>> In Lispworks,why does
>>>
>>> (funcall (lambda () (coerce (lambda () nil) 'function)))
>>>
>>> run but
>>>
>>> (funcall (lambda () (compile nil (lambda () nil))))
>>>
>>> causes  Error: #<anonymous interpreted function 200C8D82> is a
>>> lexical closure.
>>
>> There should be no difference, and no error generated.
>>
>> Are you sure lispworks generates the error you're saying, when you
>> evaluate either of those forms?
>>
>> Try with (cl:lambda () cl:nil)
>
>
> Listener output, Lispworks 6 Personal Edition, nothing  loaded. Adding
> package qualifiers everywhere:
>
>> CL-USER 5 > (cl:funcall (cl:lambda () (cl:compile cl:nil (cl:lambda ()
>> cl:nil))))
>>
>> Error: #<anonymous interpreted function 21AF2EB2> is a lexical closure.
>
>
>
>> The specification of compile is clear, the definition can be a lambda
>> expression or a function. In your case, it's a function (as returned by
>> (lambda () nil), and it doesn't matter whether it's a lexical closure,
>> an interpreted function or a compiled function.  Compile should return
>> an equivalent compiled function.
>
> Being a function does seem matter here, because the following does NOT
> signal an error
>
>> CL-USER 7 > (funcall (lambda () (compile nil '(lambda () nil))))
>> #<Function 10 21CD5F22>
>> NIL
>> NIL
>
>
> --
> ................................................
> Christopher Riesbeck
> Associate Professor, Electrical Engineering and Computer Science
> McCormick School of Engineering
> Northwestern University
>
> 2145 Sheridan Rd., Evanston, IL 60208
>
> Home page: http://www.cs.northwestern.edu/~riesbeck/
> Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html
>
> _______________________________________________
> Lisp Hug - the mailing list for LispWorks users
> lisp-hug@lispworks.com
> http://www.lispworks.com/support/lisp-hug.html
>

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: compile vs coerce

Thanks, all. For my purposes, quoting the LAMBDA inside COMPILE works fine, and I understand better most of what’s going on.

The bit seems surprising is that in the Hyperspec, COMPILE on a compiled function is either the identity operation or an equivalent wrapper, and that doesn’t suggest an error would occur. Whereas COERCE doesn’t seem to have any specification for what happens if it’s given a function already.

Thanks again


On Nov 25, 2015, at 5:04 PM, Tim Bradshaw <tfb@cley.com> wrote:



On 25 Nov 2015, at 18:43, Pascal J. Bourguignon <pjb@informatimago.com> wrote:

One could also interpret it as saying that if you're trying to compile
a closure, then you might get an error or an invalid function, but this
would be the sign of a low-quality implementation, and that would
motivate its rejection, and definitely not worth of a commercial
implementation.

I think the point was that a system might well have a different representation for lexical environments in compiled and interpreted code (and probably always does in fact) making compiling a function defined in a non-null environment at best painful  since it would either have to break the semantics of the program by splitting the environments (never OK), compile all other functions which shared the environment (not really OK, if it can even find them) or have some heroic special case.  I certainly would be fine with a system which did none of these and threw an error since I can't see this ever being useful.

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


------------------
Christopher Riesbeck
Home page: http://www.cs.northwestern.edu/~riesbeck
Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html


Re: compile vs coerce

Tim Bradshaw <tfb@cley.com> writes:

>> On 25 Nov 2015, at 18:43, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
>> 
>> One could also interpret it as saying that if you're trying to compile
>> a closure, then you might get an error or an invalid function, but this
>> would be the sign of a low-quality implementation, and that would
>> motivate its rejection, and definitely not worth of a commercial
>> implementation.
>
> I think the point was that a system might well have a different
> representation for lexical environments in compiled and interpreted
> code (and probably always does in fact) making compiling a function
> defined in a non-null environment at best painful since it would
> either have to break the semantics of the program by splitting the
> environments (never OK), 

That seems acceptable to me, given that there are a lot of other places
where you can also obtain separate closures.  For example in loops.

That wouldn't be worse than what you'd get with a lambda expression.
It would be a way to get automatically the equivalent of:

    (funcall (let ((x 42)) (eval `(let ((x ,x)) (lambda () x)))))
    --> 42

    (funcall (let ((x 42)) (compile nil (lambda () x))))
    --> 42

> compile all other functions which shared the
> environment (not really OK, if it can even find them) or have some
> heroic special case.  I certainly would be fine with a system which
> did none of these and threw an error since I can't see this ever being
> useful.

Now, other implementations don't go as far, but at least they
distinguish functions that have no free variables.  This case should be
handled properly.  (And users can always use the EVAL above instead of
COMPILE when they have free variables).

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: compile vs coerce

The specification for COERCE says: "If object is already of type result-type,
the object itself is returned..." so that matches your case.

-- 
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/


>>>>> On Wed, 25 Nov 2015 23:36:16 +0000, Christopher K Riesbeck said:
> 
> Thanks, all. For my purposes, quoting the LAMBDA inside COMPILE works fine, and I understand better most of what’s going on.
> 
> The bit seems surprising is that in the Hyperspec, COMPILE on a compiled function is either the identity operation or an equivalent wrapper, and that doesn’t suggest an error would occur. Whereas COERCE doesn’t seem to have any specification for what happens if it’s given a function already.
> 
> Thanks again
> 
> 
> On Nov 25, 2015, at 5:04 PM, Tim Bradshaw <tfb@cley.com<mailto:tfb@cley..com>> wrote:
> 
> 
> 
> On 25 Nov 2015, at 18:43, Pascal J. Bourguignon <pjb@informatimago.com<mailto:pjb@informatimago.com>> wrote:
> 
> One could also interpret it as saying that if you're trying to compile
> a closure, then you might get an error or an invalid function, but this
> would be the sign of a low-quality implementation, and that would
> motivate its rejection, and definitely not worth of a commercial
> implementation.
> 
> I think the point was that a system might well have a different representation for lexical environments in compiled and interpreted code (and probably always does in fact) making compiling a function defined in a non-null environment at best painful  since it would either have to break the semantics of the program by splitting the environments (never OK), compile all other functions which shared the environment (not really OK, if it can even find them) or have some heroic special case.  I certainly would be fine with a system which did none of these and threw an error since I can't see this ever being useful.
> 
> _______________________________________________
> Lisp Hug - the mailing list for LispWorks users
> lisp-hug@lispworks.com<mailto:lisp-hug@lispworks.com>
> http://www.lispworks.com/support/lisp-hug.html
> 
> 
> ------------------
> Christopher Riesbeck
> Home page: http://www.cs.northwestern.edu/~riesbeck
> Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html
> 
> 

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: compile vs coerce

Unable to parse email body. Email id is 13628

Updated at: 2020-12-10 08:32 UTC