[Top][All Lists]
[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