gcl-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Gcl-devel] lambda-closure and *print-level*


From: Peter Wood
Subject: Re: [Gcl-devel] lambda-closure and *print-level*
Date: Sat, 26 Oct 2002 22:23:21 +0200
User-agent: Mutt/1.4i

Hi,

On Sat, Oct 26, 2002 at 01:05:48PM -0400, Camm Maguire wrote:

> Peter Wood <address@hidden> writes:
>
> > (let ((foo nil)) (setf foo (cons (lambda () 'x) foo)) foo)
> > 
> > results in an error if *print-pretty* is t, and a segfault if it is
> > nil.  If *print-level* is set to some lowish number, GCL prints the
> > result ok.
> > 
> 
> Just a note here.  I'm not sure if the multiple-values fix I just
> committed makes a difference, but I didn't get a segfault in the
> *pretty-print* nil case, just an (apparently) endless stream of print
> output to the terminal.  How long did it take you to segfault?

I just did an update and rebuilt, and get the same behaviour.  The
segfault happens quite quickly, and doing a backtrace on the core
shows 23842 frames!
 
> GCL does have a separate type for *compiled* closures.  I haven't
> looked at how they are printed, but I would guess similarly to what
> you have above.  Of course we could come up with a scheme to
> distinguish (lambda-closure from a cons, but I'd prefer not doing
> anything too ad-hoc. 

Quite right!  Unfortunately, I do not think GCL's behaviour is
ANSI-correct.  I can't find the precise spot in the hyperspec, but
here it is in CLTL2:

================================================================
X3J13 voted in June 1988 (FUNCTION-TYPE) to revise these
specifications. The type function is to be disjoint from cons and
symbol, and so a list whose car is lambda is not, properly speaking,
of type function, nor is any symbol. However, standard Common Lisp
functions that accept functional arguments will accept a symbol or a
list whose car is lambda and automatically coerce it to be a function;
such standard functions include funcall, apply, and mapcar. Such
functions do not, however, accept a lambda-expression as a functional
argument; therefore one may not write

(mapcar '(lambda (x y) (sqrt (* x y))) p q)

but instead one must write something like

(mapcar #'(lambda (x y) (sqrt (* x y))) p q)

This change makes it impermissible to represent a lexical closure as a
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
list whose car is some special marker.

The value of a function special form will always be of type function. 
=================================================================

GCL accepts the first (disallowed) form above as well as the second.
I think this is CLTL1 specific behaviour.

> What happens in clisp/cmulisp?

Here's what a few other Cls do.
 
;clisp
1]> (lambda () 'foo)
#<closure :lambda nil 'foo>
[2]> (let ((foo nil)) (lambda () foo))
#<closure :lambda nil foo>
[3]> 

;cmu
* (lambda () 'foo)

#<Interpreted Function (LAMBDA () 'FOO) {480242B9}>
* (let ((foo nil)) (lambda () foo))

#<Interpreted Function "LET ((FOO NIL))" {48028DD1}>
* 

;ecl
> (lambda () 'foo)
#<interpreted-function 0829dba0>
> (let ((foo nil)) (lambda () foo))
#<interpreted-function 0829db40>
> 

;lispworks

CL-USER 1 > (lambda () 'foo)
#'(LAMBDA NIL (QUOTE FOO))

CL-USER 2 > (let ((foo nil)) (lambda () foo))
#<interpreted closure (LAMBDA NIL FOO)>

I think Lispworks' looks most sensible.

Regards,
Peter




reply via email to

[Prev in Thread] Current Thread [Next in Thread]