From: Antonio Menezes Leitao
Subject: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.04.28.21.51.37.283482@evaluator.pt>
Hi,

Porting Linj (my Lisp to Java compiler) to several Common Lisp compilers
has been an "interesting" experience.  I'll use this post to report the
results I got so far.

Originaly developped in CMUCL, my first attempt was to port
it to OpenMCL.  Unfortunately, there were some MOP changes between
the last two OpenMCL versions and I didn't know which version to use. 
I tried to install the last version but couldn't run it (I guess I
didn't patch it properly) so I changed to the next to last version
which was OK.  Unfortunately, I didn't had much time available to use the
Mac so, after some time trying to solve compilations errors, I had to gave
up. I'll try again latter.

CLISP was my second attempt. The first bug I found was the empty list on
macro lambda lists that I reported previously.  CLISP doesn't accept them.
I know that there are conflicting points of view in this issue but I think
CLISP is wrong about this.  I really would like to know what are they
arguments.

After adjusting my code to CLISP's taste, I found the second bug: I had a
macro character associated to a reader macro function that was returning
two values (not because I decided that way but because I was using a
function that returns two values (e.g., read-from-string)).

It happens that, according to the Hyperspec:

  Upon encountering a macro character, the Lisp reader calls its reader
  macro function, which parses one specially formatted object from the
  input stream. The function either returns the parsed object, or else it
  returns no values to indicate that the characters scanned by the
  function are being ignored (e.g., in the case of a comment).

Does this means that the reader macro function can _only_ return one or
zero values?

Or does this means that the reader macro function can return many (as long
as the first value is the parsed object) or zero values?

CMUCL prefers the second interpretation.  CLISP only accepts the first and
gives an error if you dont follow it.  What's the correct interpretation?

I decided to follow CLISP interpretation just to be compatible with both
compilers).  After this, I found several problems but, this time, I'm sure
they are real bugs in CLISP as I couldn't find a way to reconcile CLISP
implementation with the Hyperspec.  The bugs are related to pretty
printing streams and, unfortunately, they are severe enough to prevent the
Linj compiler of working correctly in CLISP.

As a result, I postponed the port to CLISP until the CLISP implementors
solve those bugs.

The next Common Lisp compiler in my list was Allegro.  Apart from the
effort needed to translate operating system dependent calls (spawning
external processes, sockets, etc) no problems where found.  At least I
don't remember them so if there were some, they weren't serious.  I do
remember that I changed the compilation order of some classes and methods
but I don't remember if it was to avoid warnings or if there were
compilation problems. Nothing relevant to report here.

Then, I moved to Lispworks.  Everything OK except that Lispworks
isn't affected by the readtable-case while printing with escaping
disabled (e.g., by princ-to-string).  This is contrary to what is
mandated by section 22.1.3.3.2 of the Hyperspec. Xanalys agree with me
that this is a bug and they told me they will solve this problem in the
next version of Lispworks. Unfortunately, this issue is fundamental for
the Linj compiler so I can compile Linj in Lispworks but I can't run
it properly.

What's next? SBCL.  Given the fact that SBCL originated from CMUCL, I
thought this would be easy.  Unfortunately, I can't compile my code
(easily) in SBCL because of problems in defconstant forms.  Let me explain
this carefully:

Let's assume a file containing the form:

(defconstant +foo+ (cons nil nil))

Due to some dependency problems (taken care in a defsystem-like
definition), this file must be compiled and loaded before other files can
be compiled. So SBCL compiles it, then proceeds to load it and it barfs
with an error when it sees that, between compilation and loading, the
value assigned to +foo+ changed.

Now, according to the Hyperspec (Macro defconstant):

  If a defconstant form appears as a top level form, the compiler must
  recognize that name names a constant variable. An implementation may
  choose to evaluate the value-form at compile time, load time, or both.
  Therefore, users must ensure that the initial-value can be evaluated at
  compile time (regardless of whether or not references to name appear in
  the file) and that it always evaluates to the same value.

So, it looks like the initial-value can be evaluated both at compile time
and at load time and both evaluations must produce the same value (if I'm
not mistaken, "same value" here means "eql").  If my reasoning is correct,
then SBCL is conforming to the Hyperspec.

Now, my question is:  How can I use the defconstant form with an initial
value that is computed (at load time) on a file that is compiled and
loaded in the same Common Lisp image?  It seems to me that the Hyperspec
is restricting the uses of defconstant in ways that simply prevents its
use for non-trivial initial values.  Or I'm I misunderstanding the
Hyperspec?

It's also strange that neither CMUCL, nor CLISP, nor Allegro, nor
Lispworks have this behaviour.


Sorry for the long post and thanks for your comments.

Best regards,

Antonio Leitao

PS: A long time ago I got a lot of experience translating programs between
Lisps (including FranzLisp, LeLisp, ZetaLisp and Common Lisp).  I was
quite happy when Common Lisp became a standard because the problems I had
making my code compatible with several Lisp implementations were over.

After my attempts to port Linj to different Common Lisp compilers, my
faith in the portability of Common Lisp programs is weaker now.  I didn't
expect to find so many problems.  I'm starting to believe that reference
implementations are better than written specifications.

From: Thomas F. Burdick
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <xcvhdv33709.fsf@famine.OCF.Berkeley.EDU>
Antonio Menezes Leitao <··············@evaluator.pt> writes:

> Now, my question is:  How can I use the defconstant form with an initial
> value that is computed (at load time) on a file that is compiled and
> loaded in the same Common Lisp image?  It seems to me that the Hyperspec
> is restricting the uses of defconstant in ways that simply prevents its
> use for non-trivial initial values.  Or I'm I misunderstanding the
> Hyperspec?

You can do something like:

  (eval-when (compile load eval)
    (unless (boundp +foo+)
      (defconstant +foo+ (cons nil nil))))

or:

  (defconstant +foo+ (if (boundp +foo+) +foo+
                         (cons nil nil)))

It would be nice if defconstant were more like defvar in this regard.

> It's also strange that neither CMUCL, nor CLISP, nor Allegro, nor
> Lispworks have this behaviour.

With CMUCL, I'm pretty sure it's possible to get yourself into weird
situations by changing the value of a constant.  IMO, having the
compiler take full advantage of a constant's constantness is a good
thing; I think SBCL does the right thing here, since it intends to
take advantage of the constant's constantness.

> PS: A long time ago I got a lot of experience translating programs between
> Lisps (including FranzLisp, LeLisp, ZetaLisp and Common Lisp).  I was
> quite happy when Common Lisp became a standard because the problems I had
> making my code compatible with several Lisp implementations were over.
> 
> After my attempts to port Linj to different Common Lisp compilers, my
> faith in the portability of Common Lisp programs is weaker now.  I didn't
> expect to find so many problems.  I'm starting to believe that reference
> implementations are better than written specifications.

Mostly, I think you're seeing how gratuitously nonconformant CLISP is.
I'd hate to think what it would be like if there weren't a written standard.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.04.29.14.58.44.243333@evaluator.pt>
On Wed, 28 Apr 2004 18:30:46 -0700, Thomas F. Burdick wrote:

> Antonio Menezes Leitao <··············@evaluator.pt> writes:
> 
>> Now, my question is:  How can I use the defconstant form with an initial
>> value that is computed (at load time) on a file that is compiled and
>> loaded in the same Common Lisp image?  It seems to me that the Hyperspec
>> is restricting the uses of defconstant in ways that simply prevents its
>> use for non-trivial initial values.  Or I'm I misunderstanding the
>> Hyperspec?
> 
> You can do something like:
> 
>   (eval-when (compile load eval)
>     (unless (boundp +foo+)
>       (defconstant +foo+ (cons nil nil))))
> 
> or:
> 
>   (defconstant +foo+ (if (boundp +foo+) +foo+
>                          (cons nil nil)))
> 

Yes.  There seems to be a general agreement that we must resort to use
boundp. (I guess you forgot some quotes in those boundp calls).

> It would be nice if defconstant were more like defvar in this regard.

Is there anyone from the X3J13 committee available to comment on this?

Thanks,

Antonio Leitao.
From: Bruno Haible
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c6rdpd$n0c$2@laposte.ilog.fr>
Thomas F. Burdick wrote:
>
> I think you're seeing how gratuitously nonconformant CLISP is.

Let's see whether this accusation is unfounded or not.

What is your preferred Lisp implementation?

How many failures does it show w.r.t. Paul Dietz' ansi-tests testsuite?

And how many of them are documented, i.e. deliberate?

                Bruno
From: Thomas F. Burdick
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <xcvbrl82czh.fsf@famine.OCF.Berkeley.EDU>
Bruno Haible <·····@clisp.org> writes:

> Thomas F. Burdick wrote:
> >
> > I think you're seeing how gratuitously nonconformant CLISP is.
> 
> Let's see whether this accusation is unfounded or not.
> 
> What is your preferred Lisp implementation?

I'm not sure how that shows whether my statement was founded or not.
I used to primarily use CMUCL, but nowadays I do my work in SBCL.
When I'm not using CLISP, that is.

> How many failures does it show w.r.t. Paul Dietz' ansi-tests testsuite?

I really don't know, but numbers aren't everything:

> And how many of them are documented, i.e. deliberate?

That's exactly what kills me about CLISP.  It's a mature, high quality
Lisp implementation, with long-standing, documented deviations wrt the
CL standard.  I don't follow CLISP development anymore, so I'm not
sure how much better it's getting, but over the last several years,
CLISP's nonconformities have actually gotten in the way of real work,
and some of the CLOS shortcommings have required me to write ugly
hacks where I should have been able to write an elegant, maintainable
solution using the standard language.

Whatever the numbers from Dietz' test suite, CMUCL's and SBCL's
conformance bugs haven't made me feel like I was writing code with my
hands tied.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Bruno Haible
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c732bi$spi$1@laposte.ilog.fr>
Thomas F. Burdick wrote:
> CLISP's nonconformities have actually gotten in the way of real work,
> and some of the CLOS shortcommings have required me to write ugly
> hacks where I should have been able to write an elegant, maintainable
> solution using the standard language.

The "CLOS shortcomings" of clisp before/up to version 2.33 consist of:

  - Lack of CHANGE-CLASS. I don't see how this monster can lead you to
    elegant, maintainable programs. Rather, doing a design that avoids
    CHANGE-CLASS will lead to more elegant programs.

  - Lack of UPDATE-INSTANCE-FOR-REDEFINED-CLASS. This is an issue that
    hinders you from developing in the same Lisp session for a whole
    week, i.e. it's an issue of the development environment. But it
    should have no effect on the programs you can write.

  - The fact that the metaclass of CLASS is STRUCTURE-CLASS instead of
    STANDARD-CLASS is a small trouble. But it cannot hinder you to
    program since subclassing CLASS is not useful without a good MOP,
    i.e. with just the ANSI CL things.

  - Lack of DEFINE-METHOD-COMBINATION. Ok, that can be a problem, once
    in 5 years.

Bruno
From: Thomas F. Burdick
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <xcv7jvu3fxs.fsf@famine.OCF.Berkeley.EDU>
Bruno Haible <·····@clisp.org> writes:

> Thomas F. Burdick wrote:
> > CLISP's nonconformities have actually gotten in the way of real work,
> > and some of the CLOS shortcommings have required me to write ugly
> > hacks where I should have been able to write an elegant, maintainable
> > solution using the standard language.
> 
> The "CLOS shortcomings" of clisp before/up to version 2.33 consist of:
> 
>   - Lack of CHANGE-CLASS. I don't see how this monster can lead you to
>     elegant, maintainable programs. Rather, doing a design that avoids
>     CHANGE-CLASS will lead to more elegant programs.

No.  Wrong.  Sometimes, CHANGE-CLASS is an elegant solution.  If the
flow of your program logic involves needing to instantiate an object,
but later recieving more information about it, that would best be
encoded as type information -- what you want is CHANGE-CLASS.  You can
hack around it, but it'll usually be ugly.

>   - Lack of UPDATE-INSTANCE-FOR-REDEFINED-CLASS. This is an issue that
>     hinders you from developing in the same Lisp session for a whole
>     week, i.e. it's an issue of the development environment. But it
>     should have no effect on the programs you can write.

What?!?!  Patching a running application is a very useful thing.
CLISP forces me to use a C++-like style of guessing what classes might
need patching, and using container objects for an extra level of
indirection.  That was cool when I primarily used C++, but now I know
better.  Trying to keep a semblance of object identity here is horrible.

And it's not just u-i-f-r-c that's missing.  That's a somewhat oblique
way of referring to the fact that CLISP renders all the instances of a
class obsolete when you redefine the class.  Damn.

>   - The fact that the metaclass of CLASS is STRUCTURE-CLASS instead of
>     STANDARD-CLASS is a small trouble. But it cannot hinder you to
>     program since subclassing CLASS is not useful without a good MOP,
>     i.e. with just the ANSI CL things.

We can agree on this one :-)

>   - Lack of DEFINE-METHOD-COMBINATION. Ok, that can be a problem, once
>     in 5 years.

Wow.  I can only assume that you haven't worked in a Lisp that has
support for method combinations, or you've managed to find only those
problems that fit within the model of the standard method combination.

It's not just user-defined method combinations, though.  Part of the
reason Lispers don't write too many of their own is that the standard
defines several useful method combinations, including PROGN and +.

Just because you can get work done with CLISP doesn't mean you're not
also missing a lot.  I can get work done with emacs lisp, too.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: John Thingstad
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <opr7drmmmvxfnb1n@news.chello.no>
uhum! This case from my fastcgi interface becomes a unruly mess without 
change class.

(defmacro extend-class (instance class slots func)
   `(progn
      (change-class ,instance ,class)
      (with-slots ,slots ,instance
       (multiple-value-setq ,slots ,func))))

(defun parse-record (stream)
   (let ((record (make-instance 'record)))
     (with-slots (version type request-id contents-length padding-length 
reserved
		 contents-data padding-data) record
      (let ((bytes (make-array +record-length+ :element-type 'char)))
        (read-sequence bytes stream)
        (setf version (aref bytes 0))
        (setf type (aref bytes 1))
        (setf request-id (2bi (aref bytes 2) (aref bytes 3)))
        (setf contents-length (2bi (aref bytes 4) (aref bytes 5)))
        (setf padding-length (aref bytes 6))
        (setf reserved (aref bytes 7))
        (setf contents-data (make-array contents-length :element-type 
'byte))
        (setf padding-data (make-array padding-data padding-length 
:element-type 'byte))
        (read-sequence contents-data stream)
        (read-sequence padding-data stream)
        (case type
	 (+begin-request+
	  (extend-class record 'begin-request
			(role flags reserved)
			(parse-begin-request contents-data)))
	 (+abort-request+
	  (change-class record 'abort-request))
	 (+end-request+
	  (extend-class record 'end-request
			(app-status protocol-status reserved)
			(parse-end-request contents-data)))
	 (+params+
	  (change-class record 'params)
	  (setf (nv-list record) (parse-nv-list contents-data)))
	 (+stdin+
	  (change-class record 'stdin)
	  (setf (string-data record) (byte-seq->string contents-data)))
	 (+stdout+
	  (change-class record 'stdout)
	  (setf (string-data record) (byte-seq->string contents-data)))
	 (+stderr+
	  (change-class record 'stderr)
	  (setf (string-data record) (byte-seq->string contents-data)))
	 (+data+
	  (change-class record 'data)
	  (setf (string-data record) (byte-seq->string contents-data)))
	 (+get-values+
	  (change-class record 'get-values)
	  (setf (nv-list record) (parse-nv-list contents-data)))
	 (+get-values-result+
	  (change-class record 'get-values-result))
	 (+unknown-type+
	  (extend-class record 'unknown-type
			(type reserved)
			(parse-unknown-type contents-data)))
	 (otherwise (error "incorrect type")))))
     record))



P� 2 May 2004 14:58:58 GMT, skrev Bruno Haible <·····@clisp.org>:

> Thomas F. Burdick wrote:
>> CLISP's nonconformities have actually gotten in the way of real work,
>> and some of the CLOS shortcommings have required me to write ugly
>> hacks where I should have been able to write an elegant, maintainable
>> solution using the standard language.
>
> The "CLOS shortcomings" of clisp before/up to version 2.33 consist of:
>
>   - Lack of CHANGE-CLASS. I don't see how this monster can lead you to
>     elegant, maintainable programs. Rather, doing a design that avoids
>     CHANGE-CLASS will lead to more elegant programs.
>
>   - Lack of UPDATE-INSTANCE-FOR-REDEFINED-CLASS. This is an issue that
>     hinders you from developing in the same Lisp session for a whole
>     week, i.e. it's an issue of the development environment. But it
>     should have no effect on the programs you can write.
>
>   - The fact that the metaclass of CLASS is STRUCTURE-CLASS instead of
>     STANDARD-CLASS is a small trouble. But it cannot hinder you to
>     program since subclassing CLASS is not useful without a good MOP,
>     i.e. with just the ANSI CL things.
>
>   - Lack of DEFINE-METHOD-COMBINATION. Ok, that can be a problem, once
>     in 5 years.
>
> Bruno



-- 
Sender med M2, Operas revolusjonerende e-postprogram: http://www.opera.com/
From: Bruno Haible
Subject: Re: change-class (was: The Hyperspec and portability between Common Lisp compilers (long))
Date: 
Message-ID: <c7390c$5jn$1@laposte.ilog.fr>
John Thingstad wrote:
>
> (defmacro extend-class (instance class slots func)
>   `(progn
>      (change-class ,instance ,class)
>      (with-slots ,slots ,instance
>       (multiple-value-setq ,slots ,func))))

Agreed, changing the class of an instance to become a _subclass_ of its
previous class is very clean and consistent with OO. It's only the other
cases that are monstruous.

clisp-2.34 will fully support CHANGE-CLASS.

         Bruno

PS: Other programming languages know about CHANGE-CLASS as well. For
example, in C++, when a new object is created, it is created as an
instance of the root class, without slots and methods, and it is only
at the beginning of each INITIALIZE-INSTANCE primary method (called
"constructor" in C++ speak) for each class that the object is
changed to become an instance of the class on which the method is
specialized. So C++ conceptually knows about CHANGE-CLASS but is
afraid to say so...
From: Paolo Amoroso
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <87vfjdio4y.fsf@plato.moon.paoloamoroso.it>
Bruno Haible <·····@clisp.org> writes:

> The "CLOS shortcomings" of clisp before/up to version 2.33 consist of:
[...]
>   - Lack of DEFINE-METHOD-COMBINATION. Ok, that can be a problem, once
>     in 5 years.

This comment from the ASDF code might be relevant:

  ;;; So you look at this code and think "why isn't it a bunch of
  ;;; methods".  And the answer is, because standard method combination
  ;;; runs :before methods most->least-specific, which is back to front
  ;;; for our purposes.  And CLISP doesn't have non-standard method
  ;;; combinations, so let's keep it simple and aspire to portability


Paolo
-- 
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Pascal Costanza
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c78qjl$fuv$1@newsreader2.netcologne.de>
Bruno Haible wrote:

> Thomas F. Burdick wrote:
> 
>>CLISP's nonconformities have actually gotten in the way of real work,
>>and some of the CLOS shortcommings have required me to write ugly
>>hacks where I should have been able to write an elegant, maintainable
>>solution using the standard language.
> 
> 
> The "CLOS shortcomings" of clisp before/up to version 2.33 consist of:

Are they documented somewhere (apart form here ;). I would expect them 
to be listed in the FAQ "What about ANSI compliance?" (or a similar 
section "What about MOP compliance?".

>   - Lack of CHANGE-CLASS. I don't see how this monster can lead you to
>     elegant, maintainable programs. Rather, doing a design that avoids
>     CHANGE-CLASS will lead to more elegant programs.

Changing a class to a subclass, to a superclass and to a sibling class 
are useful.

>   - Lack of DEFINE-METHOD-COMBINATION. Ok, that can be a problem, once
>     in 5 years.

DEFINE-METHOD-COMBINATION was one of the features in Common Lisp that 
finally convinced me to switch. It was a natural way to solve a very 
nasty problem in one of my first CL programs.


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Christophe Rhodes
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <sqd65mzwff.fsf@lambda.dyndns.org>
Bruno Haible <·····@clisp.org> writes:

> What is your preferred Lisp implementation?
>
> How many failures does it show w.r.t. Paul Dietz' ansi-tests
> testsuite?

Oh come now.  Paul's tests are a wonderful boon for implementors,
allowing them to track isolated nonconformances easily (and even some
second-order interactions between parts of the system) but surely
you're not advocating that implementations' conformance be measured by
counting failed tests?  It could be a useful datum in certain
circumstances, but even at this relatively advanced stage there are
whole areas of the specification that are untested; in addition, the
very fact that the test suite is not intended to produce a conformance
measure limits its utility in that regard.

Finally, of course, some non-conformances are more significant than
others for someone wishing to program in Common Lisp, simply because
programs in the wild leave codepaths unexplored.

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Paul F. Dietz
Subject: Re: The Hyperspec and portability between Common Lisp compilers
Date: 
Message-ID: <c56dnSTGxdFLswjdRVn-hA@dls.net>
Christophe Rhodes wrote:

>   It could be a useful datum in certain
> circumstances, but even at this relatively advanced stage there are
> whole areas of the specification that are untested; in addition, the
> very fact that the test suite is not intended to produce a conformance
> measure limits its utility in that regard.

I want to emphasize that the test suite is not intended to be a means
to compute how closely an implementation conforms to the specification.
Rather, it is: (1) a tool to help implementors improve and maintain
conformance, and (2) a means to explore problematic parts of
the ANSI spec itself.

	Paul
From: Bruno Haible
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c73a55$6n4$1@laposte.ilog.fr>
Christophe Rhodes wrote:
> surely you're not advocating that implementations' conformance be
> measured by counting failed tests?

Still the number of failed tests gives an indication how serious the
implementors take the standard. If two implementations come out with
53 resp. 54 failures, you cannot draw any conclusions from it. But if
one comes out with 20 failures and the other one with 100 failures,
then you can draw conclusions.

It is not unusual in the Linux camp to compare distributions according
to the number of failures w.r.t. the FHS, ABI and OpenI18N testsuites.

              Bruno
From: Christophe Rhodes
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <sq8ygazqid.fsf@lambda.dyndns.org>
Bruno Haible <·····@clisp.org> writes:

> Christophe Rhodes wrote:
>> surely you're not advocating that implementations' conformance be
>> measured by counting failed tests?
>
> Still the number of failed tests gives an indication how serious the
> implementors take the standard. 

Or how often they release, or their established user base, or their
strategy for dealing with standard bugs, or their manpower free to
deal with corner cases that aren't customer-driven.  I agree though
that one can conceivably draw an inference, but I wouldn't like to
make it a strong one.

> If two implementations come out with 53 resp. 54 failures, you
> cannot draw any conclusions from it. But if one comes out with 20
> failures and the other one with 100 failures, then you can draw
> conclusions.

Be explicit: tell me what conclusion you would draw given just those
two numbers, 20 and 100, for two different implementations released on
the same day.  I am likely to argue that almost any conclusion with
any bite is misguided; if the conclusion you are proposing is
something like "the implementation with 100 failures is less
ANSI-compliant than the one with 20", I certainly will, because there
isn't any kind of evaluation of the scope of the failures within the
system, nor the impact of the failures, nor the evolution with time.

> It is not unusual in the Linux camp to compare distributions according
> to the number of failures w.r.t. the FHS, ABI and OpenI18N testsuites.

It's not unusual in the softer sciences to quote measurements without
giving any indication of the accuracy of such a measurement.  That
doesn't make it valid to draw rigid conclusions from them.

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Pascal Costanza
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c6pgcv$do$1@newsreader2.netcologne.de>
Antonio Menezes Leitao wrote:

> It happens that, according to the Hyperspec:
> 
> Upon encountering a macro character, the Lisp reader calls its reader
> macro function, which parses one specially formatted object from the
> input stream. The function either returns the parsed object, or else
> it returns no values to indicate that the characters scanned by the 
> function are being ignored (e.g., in the case of a comment).
> 
> Does this means that the reader macro function can _only_ return one
> or zero values?

Nope. The glossary says this:

"value n. 1. a. one of possibly several objects that are the result of
an evaluation. b. (in a situation where exactly one value is expected
from the evaluation of a form) the primary value returned by the form.
[...]"

...and...

"primary value n. (of values resulting from the evaluation of a form)
the first value, if any, or else nil if there are no values. [...]"

So I think this is a very clear situation.

> What's next? SBCL.  Given the fact that SBCL originated from CMUCL, I
> thought this would be easy.  Unfortunately, I can't compile my code 
> (easily) in SBCL because of problems in defconstant forms.  Let me
> explain this carefully:
> 
> Let's assume a file containing the form:
> 
> (defconstant +foo+ (cons nil nil))
> 
> Due to some dependency problems (taken care in a defsystem-like 
> definition), this file must be compiled and loaded before other files
> can be compiled. So SBCL compiles it, then proceeds to load it and it
> barfs with an error when it sees that, between compilation and
> loading, the value assigned to +foo+ changed.
> 
> Now, according to the Hyperspec (Macro defconstant):
> 
> If a defconstant form appears as a top level form, the compiler must 
> recognize that name names a constant variable. An implementation may 
> choose to evaluate the value-form at compile time, load time, or
> both. Therefore, users must ensure that the initial-value can be
> evaluated at compile time (regardless of whether or not references to
> name appear in the file) and that it always evaluates to the same
> value.

...but (cons ...) by definition doesn't always evaluate to the same
value. It always produces a fresh cons cell. You have basically the
following options, AFAICS:

(defconstant +foo+ #.(cons nil nil))

or

(defvar *foo* (cons nil nil))

> After my attempts to port Linj to different Common Lisp compilers, my
> faith in the portability of Common Lisp programs is weaker now.  I
> didn't expect to find so many problems.  I'm starting to believe that
> reference implementations are better than written specifications.

That's the same as choosing only one CL implementation and not caring
about others.


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Paul F. Dietz
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <SPOdnVIeab6L_Q3dRVn-uw@dls.net>
Pascal Costanza wrote:

> ...but (cons ...) by definition doesn't always evaluate to the same
> value. It always produces a fresh cons cell. You have basically the
> following options, AFAICS:
> 
> (defconstant +foo+ #.(cons nil nil))
> 
> or
> 
> (defvar *foo* (cons nil nil))

I suggest:

(defvar +foo+ (if (boundp +foo+) +foo+ (cons nil nil)))

IIRC, SBCL has a (nonstandard) macro that expands to this.

	Paul
From: Pascal Costanza
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c6qd8d$kk6$2@newsreader2.netcologne.de>
Paul F. Dietz wrote:

> I suggest:
> 
> (defvar +foo+ (if (boundp +foo+) +foo+ (cons nil nil)))

Did you actually mean defconstant here?


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Paul F. Dietz
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <5ZOdnUITGohhfw3dRVn-sA@dls.net>
Pascal Costanza wrote:

> Did you actually mean defconstant here?

Er, yes.

	Paul
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.04.29.14.35.34.982584@evaluator.pt>
On Thu, 29 Apr 2004 06:14:54 -0500, Paul F. Dietz wrote:

> Pascal Costanza wrote:

>> Paul F. Dietz wrote:

>>> I suggest:
>>> 
>>> (defvar +foo+ (if (boundp +foo+) +foo+ (cons nil nil)))

>> Did you actually mean defconstant here?
> 
> Er, yes.

If I understand correctly, you are suggesting:

(defconstant +foo+ (if (boundp '+foo+) +foo+ (cons nil nil)))
                               ^
                               |
                               quote missing

I think it works but I also get a compiler warning regarding
the obviously undefined variable +foo+ that occurs in the second argument
of the if.  Given the specialness status that some Lisps automatically
assign to undefined variables, I'm afraid it might introduce some
unintended semantic problems.  Although constant variables might be
declared special by some compilers, they might also not be declared
special (see DEFCONSTANT-SPECIAL:NO issue in macro defconstant).

Maybe it is more correct to write:

(defconstant +foo+ (if (boundp '+foo+) (symbol-value '+foo+) (cons nil nil)))

At least, SBCL stops complaining with this form.

Thanks for the suggestion,

Antonio Leitao.
From: Thomas F. Burdick
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <xcvekq42det.fsf@famine.OCF.Berkeley.EDU>
Antonio Menezes Leitao <··············@evaluator.pt> writes:

> If I understand correctly, you are suggesting:
> 
> (defconstant +foo+ (if (boundp '+foo+) +foo+ (cons nil nil)))
>                                ^
>                                |
>                                quote missing

I'm guessing the sloppiness of the suggestions you got were because
those of us who do this probably all wrap the logic up in a macro.  I
checked, and my DEFCONSTANT-ONCE macro expands to:

> Maybe it is more correct to write:
> 
> (defconstant +foo+ (if (boundp '+foo+) (symbol-value '+foo+) (cons nil nil)))
> 
> At least, SBCL stops complaining with this form.

Precisely because of the undeclared-variable warning :-)

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Rahul Jain
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <871xm4f0qe.fsf@nyct.net>
Antonio Menezes Leitao <··············@evaluator.pt> writes:

> I think it works but I also get a compiler warning regarding
> the obviously undefined variable +foo+ that occurs in the second argument
> of the if.  Given the specialness status that some Lisps automatically
> assign to undefined variables, I'm afraid it might introduce some
> unintended semantic problems.

A warning is just a warning. You know that the variable is never used if
unbound, so there's no problem. Your proposed change is fine, though, if
warnings really do scare the living bejeezus out of you.

> Although constant variables might be
> declared special by some compilers, they might also not be declared
> special (see DEFCONSTANT-SPECIAL:NO issue in macro defconstant).

What does this have to do with the issue? Constants can't be rebound in
any way, by definition.

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.05.02.11.58.18.436152@evaluator.pt>
On Sat, 01 May 2004 18:42:20 +0000, Rahul Jain wrote:

> Antonio Menezes Leitao <··············@evaluator.pt> writes:
> 
>> Although constant variables might be
>> declared special by some compilers, they might also not be declared
>> special (see DEFCONSTANT-SPECIAL:NO issue in macro defconstant).
> 
> What does this have to do with the issue? Constants can't be rebound in
> any way, by definition.

Well, it would seem plausible to me that, upon compilation of an
expression containing what seems to be an undefined variable, the compiler
decided to declare it special and this declaration could then conflict
with the subsequent defconstant form for the same variable because
constants and special vars might have different compilation strategies.

Best regards,

Antonio Leitao.
From: Rahul Jain
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <871xm2eqzk.fsf@nyct.net>
Antonio Menezes Leitao <··············@evaluator.pt> writes:

> Well, it would seem plausible to me that, upon compilation of an
> expression containing what seems to be an undefined variable, the compiler
> decided to declare it special and this declaration could then conflict
> with the subsequent defconstant form for the same variable because
> constants and special vars might have different compilation strategies.

It wouldn't be able to. The declaration would be local to that form. It
would seem plausible to ME that such a declaration wouldn't stop the
code from working as intended, in any case. Otherwise symbol-value
wouldn't work as specified, assuming an implementation that isn't doing
anything particuarly funky.

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.04.29.06.08.52.643164@evaluator.pt>
On Thu, 29 Apr 2004 01:57:18 +0200, Pascal Costanza wrote:

> 
> Antonio Menezes Leitao wrote:
> 
>> It happens that, according to the Hyperspec:
>> 
>> Upon encountering a macro character, the Lisp reader calls its reader
>> macro function, which parses one specially formatted object from the
>> input stream. The function either returns the parsed object, or else
>> it returns no values to indicate that the characters scanned by the 
>> function are being ignored (e.g., in the case of a comment).
>> 
>> Does this means that the reader macro function can _only_ return one
>> or zero values?
> 
> Nope. The glossary says this:
> 
> "value n. 1. a. one of possibly several objects that are the result of
> an evaluation. b. (in a situation where exactly one value is expected
> from the evaluation of a form) the primary value returned by the form.
> [...]"
> 
> ...and...
> 
> "primary value n. (of values resulting from the evaluation of a form)
> the first value, if any, or else nil if there are no values. [...]"
> 
> So I think this is a very clear situation.

I would like to think that you are wright but I'm not sure.  The reader
macro function definition does not mention "value".  In fact, it looks
like the caller is exploring a protocol that takes into account the number
of returned values.

I would really appreciate if CLISP's authors explained their position
so that we can settle these questions once and for all.

Thanks for your comments,

Antonio Leitao.
From: Pascal Costanza
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c6qd6r$kk6$1@newsreader2.netcologne.de>
Antonio Menezes Leitao wrote:

> On Thu, 29 Apr 2004 01:57:18 +0200, Pascal Costanza wrote:

>>The glossary says this:
>>
>>"value n. 1. a. one of possibly several objects that are the result of
>>an evaluation. b. (in a situation where exactly one value is expected
>>from the evaluation of a form) the primary value returned by the form.
>>[...]"
>>
>>...and...
>>
>>"primary value n. (of values resulting from the evaluation of a form)
>>the first value, if any, or else nil if there are no values. [...]"
>>
>>So I think this is a very clear situation.
> 
> I would like to think that you are wright but I'm not sure.  The reader
> macro function definition does not mention "value".  In fact, it looks
> like the caller is exploring a protocol that takes into account the number
> of returned values.

Section 2 "Reader Algorithm" states in step 4:

"The reader macro function may return zero values or one value. If one 
value is returned, then that value is returned as the result of the read 
operation; the algorithm is done. If zero values are returned, then step 
1 is re-entered."

Together with the two glossary entries above, this is really unambiguous.


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Lars Brinkhoff
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <85ad0vdvug.fsf@junk.nocrew.org>
Pascal Costanza wrote:
> > > The glossary says this:
> > >
> > > "value n. 1. a. one of possibly several objects that are the
> > > result of an evaluation. b. (in a situation where exactly one
> > > value is expected from the evaluation of a form) the primary
> > > value returned by the form.  [...]"
> > >
> > > ...and...
> > >
> > > "primary value n. (of values resulting from the evaluation of a
> > > form) the first value, if any, or else nil if there are no
> > > values. [...]"
> 
> Section 2 "Reader Algorithm" states in step 4:
> 
> "The reader macro function may return zero values or one value. If
> one value is returned, then that value is returned as the result of
> the read operation; the algorithm is done. If zero values are
> returned, then step 1 is re-entered."
> 
> Together with the two glossary entries above, this is really
> unambiguous.

Perhaps not.  The sentence "The reader macro function may return zero
values or one value." doesn't exactly describe "a situation where
exactly one value is expected from the evaluation of a form".

-- 
Lars Brinkhoff,         Services for Unix, Linux, GCC, HTTP
Brinkhoff Consulting    http://www.brinkhoff.se/
From: Pascal Costanza
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c6qfbt$oo6$2@newsreader2.netcologne.de>
Lars Brinkhoff wrote:

> Perhaps not.  The sentence "The reader macro function may return zero
> values or one value." doesn't exactly describe "a situation where
> exactly one value is expected from the evaluation of a form".

But then again, why should the reader _insist_ on getting either zero or 
one value, but not more? That doesn't make sense to me.


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Lars Brinkhoff
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <8565bjdufx.fsf@junk.nocrew.org>
Pascal Costanza <········@web.de> writes:
> Lars Brinkhoff wrote:
> > Perhaps not.  The sentence "The reader macro function may return
> > zero values or one value." doesn't exactly describe "a situation
> > where exactly one value is expected from the evaluation of a
> > form".
> But then again, why should the reader _insist_ on getting either
> zero or one value, but not more? That doesn't make sense to me.

I agree, but if the CLISP developers claim they conform to the letter
of the specification (in this case), they might have a point.

Another one for "Proposed ANSI Revisions and Clarifications", I guess.

-- 
Lars Brinkhoff,         Services for Unix, Linux, GCC, HTTP
Brinkhoff Consulting    http://www.brinkhoff.se/
From: Bruno Haible
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c6rcs4$n0c$1@laposte.ilog.fr>
Antonio Menezes Leitao wrote:
> I would really appreciate if CLISP's authors explained their position
> so that we can settle these questions once and for all.

CLHS section 2.2.(4):
  "The reader macro function may return zero values or one value. If
   one value is returned, then that value is returned as the result of
   the read operation; the algorithm is done. If zero values are
   returned, then step 1 is re-entered."

This is a protocol between the reader algorithm and the reader macro,
i.e. between the implementation and your program.

In such situations, an implementation generally has the choice between
lenient behaviour - you can also say: "garbage in, garbage out" principle -,
and strict behaviour - to signal an error as early as possible.

CLISP in such situations always chooses the "maximum error checking"
behaviour, in order to make the developer aware of his errors as early
as possible, and thereby reduce the time needed for debugging.

                   Bruno
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.04.29.17.54.28.958549@evaluator.pt>
On Thu, 29 Apr 2004 17:09:24 +0000, Bruno Haible wrote:

> Antonio Menezes Leitao wrote:
>> I would really appreciate if CLISP's authors explained their position
>> so that we can settle these questions once and for all.
> 
> CLHS section 2.2.(4):
>   "The reader macro function may return zero values or one value. If
>    one value is returned, then that value is returned as the result of
>    the read operation; the algorithm is done. If zero values are
>    returned, then step 1 is re-entered."
> 
> This is a protocol between the reader algorithm and the reader macro,
> i.e. between the implementation and your program.
> 
> In such situations, an implementation generally has the choice between
> lenient behaviour - you can also say: "garbage in, garbage out" principle -,
> and strict behaviour - to signal an error as early as possible.
> 
> CLISP in such situations always chooses the "maximum error checking"
> behaviour, in order to make the developer aware of his errors as early
> as possible, and thereby reduce the time needed for debugging.
> 

I'm ready to agree with you on this issue.  In fact, I've always expressed
some doubts regarding the interpretation that allows multiple return
values from the reader macro function.

Now, I would be glad if you could tell us your opinion regarding
empty lists in macro lambda lists.

Thanks a lot for your answer.

Antonio Leitao.
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.04.29.07.45.38.539569@evaluator.pt>
On Thu, 29 Apr 2004 01:57:18 +0200, Pascal Costanza wrote:

> You have basically the
> following options, AFAICS:
> 
> (defconstant +foo+ #.(cons nil nil))
>
>

Nope.  That will not work because after reading the code (but before
compilation or evaluation, you get

(defconstant +foo+ (nil))

which is not correct.

Maybe you were talking about

(defconstant +foo+ '#.(cons nil nil))

I had thought about (and tryed) this before but it can't work.  The
Hyperspec says (in section 3.2.4.1 Externalizable Objects):

  The file compiler must cooperate with the loader in order to assure that
  in each case where an externalizable object is processed as a literal
  object, the loader will construct a similar object.

However, the definition of "similar" object doesn't imply "eql" object as
demanded by defconstant: (3.2.4.2.2 Definition of Similarity)

  Two conses, S and C, are similar if the car[2] of S is similar to the
  car[2] of C, and the cdr[2] of S is similar to the cdr[2] of C.

So, the conses don't need to be eql.  Or am I missing something?

Thanks for your comments,

Antonio Leitao
From: Pascal Costanza
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c6qf7h$oo6$1@newsreader2.netcologne.de>
Antonio Menezes Leitao wrote:

> Maybe you were talking about
> 
> (defconstant +foo+ '#.(cons nil nil))
> 
> I had thought about (and tryed) this before but it can't work.

Maybe load-time-value is what you need. (I haven't completely understood 
load-time-value yet myself, though...)


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Paul F. Dietz
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <no2dnbBzCK92fg3dRVn-tA@dls.net>
Pascal Costanza wrote:

> Maybe load-time-value is what you need. (I haven't completely understood 
> load-time-value yet myself, though...)

I've used LOAD-TIME-VALUE for that effect (to guarantee that certain
objects in compiled files are EQ after loading, not just similar.)

	Paul
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.04.29.12.47.55.960155@evaluator.pt>
On Thu, 29 Apr 2004 06:18:52 -0500, Paul F. Dietz wrote:

> Pascal Costanza wrote:
> 
>> Maybe load-time-value is what you need. (I haven't completely understood 
>> load-time-value yet myself, though...)
> 
> I've used LOAD-TIME-VALUE for that effect (to guarantee that certain
> objects in compiled files are EQ after loading, not just similar.)
> 

Someone suggested me the same idea by private email.  I will explain
my conclusions.

The relevant paragraph from the Hyperspec says:

  If a load-time-value expression is processed by compile-file, the
  compiler performs its normal semantic processing (such as macro
  expansion and translation into machine code) on form, but arranges
  for the execution of form to occur at load time in a null lexical
  environment, with the result of this evaluation then being treated
  as a literal object at run time. It is guaranteed that the
  evaluation of form will take place only once when the file is
  loaded, but the order of evaluation with respect to the evaluation
  of top level forms in the file is implementation-dependent.

My English skills aren't as good as I would like them to be but it
looks to me that the preceding paragraph doesn't say anything about
evaluation of the load-time-value expression at compile time (and it
doesn't prevent it).

The Hyperspec also says:

  If the same list (load-time-value form) is evaluated or compiled
  more than once, it is implementation-dependent whether form is
  evaluated only once or is evaluated more than once. This can happen
  both when an expression being evaluated or compiled shares
  substructure, and when the same form is processed by eval or compile
  multiple times. Since a load-time-value expression can be referenced
  in more than one place and can be evaluated multiple times by eval,
  it is implementation-dependent whether each execution returns a
  fresh object or returns the same object as some other
  execution. Users must use caution when destructively modifying the
  resulting object.

This means that a form such as 

(defconstant +foo+ (load-time-value (foo)))

might evaluate (foo) at compile time and then again at load time, each
time producing a different value and violating defconstant
assumptions.

Can you explain me your idea regarding load-time-value?

Best regards,

Antonio Leitao.
From: Paul F. Dietz
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <grGdnfJ_R9HUmQzdRVn-hQ@dls.net>
Antonio Menezes Leitao wrote:

>   If a load-time-value expression is processed by compile-file, the
>   compiler performs its normal semantic processing (such as macro
>   expansion and translation into machine code) on form, but arranges
>   for the execution of form to occur at load time in a null lexical
>   environment, with the result of this evaluation then being treated
>   as a literal object at run time. It is guaranteed that the
>   evaluation of form will take place only once when the file is
>   loaded, but the order of evaluation with respect to the evaluation
>   of top level forms in the file is implementation-dependent.
> 
> My English skills aren't as good as I would like them to be but it
> looks to me that the preceding paragraph doesn't say anything about
> evaluation of the load-time-value expression at compile time (and it
> doesn't prevent it).

Huh?  It says it evaluates the form at load time.  Load time != compile time.

	Paul
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.04.29.14.14.09.805542@evaluator.pt>
On Thu, 29 Apr 2004 08:36:59 -0500, Paul F. Dietz wrote:

> Antonio Menezes Leitao wrote:
> 
>>   If a load-time-value expression is processed by compile-file, the
>>   compiler performs its normal semantic processing (such as macro
>>   expansion and translation into machine code) on form, but arranges
>>   for the execution of form to occur at load time in a null lexical
>>   environment, with the result of this evaluation then being treated
>>   as a literal object at run time. It is guaranteed that the
>>   evaluation of form will take place only once when the file is
>>   loaded, but the order of evaluation with respect to the evaluation
>>   of top level forms in the file is implementation-dependent.
>> 
>> My English skills aren't as good as I would like them to be but it
>> looks to me that the preceding paragraph doesn't say anything about
>> evaluation of the load-time-value expression at compile time (and it
>> doesn't prevent it).
> 
> Huh?  It says it evaluates the form at load time.  Load time != compile time.
> 
> 	Paul

If you are compiling _and_ loading the file (as happens with any
defsystem) the form will be evaluated both at compile time _and_ at load
time on the same Common Lisp image.  This will produce different values
and the second evaluation of the defconstant form will generate an error.

Antonio Leitao.
From: Paul F. Dietz
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <5budnfPh_dZ8hAzd4p2dnA@dls.net>
Antonio Menezes Leitao wrote:

> If you are compiling _and_ loading the file (as happens with any
> defsystem) the form will be evaluated both at compile time _and_ at load
> time on the same Common Lisp image.  This will produce different values
> and the second evaluation of the defconstant form will generate an error.

Ah.  What I was using LOAD-TIME-VALUE for was to evaluate a form that
looked up in a global table to see if the desired value had already
been computed.  That is, if the value was EQUAL to something that
had already been computed this way, the existing object was used.

It wouldn't matter if you had already evaluated this at compile
time, since that would just store the object into the table for
later reuse at load time.

	Paul
From: Pascal Costanza
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c6r6dh$197g$1@f1node01.rhrz.uni-bonn.de>
A meta comment / question:

Why don't you just use defvar or defparameter when it turns out that 
defconstant doesn't do the right thing? This looks to me like wasting 
too much time on something that probably doesn't buy you much. I am just 
curious...


Pascal

-- 
ECOOP 2004 Workshops - Oslo, Norway
*1st European Lisp and Scheme Workshop, June 13*
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
*2nd Post-Java Workshop, June 14*
http://prog.vub.ac.be/~wdmeuter/PostJava04/
From: Dave Pearson
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <slrnc92fab.cth.davep.news@hagbard.davep.org>
* Pascal Costanza <········@web.de>:

> Why don't you just use defvar or defparameter when it turns out that
> defconstant doesn't do the right thing? This looks to me like wasting too
> much time on something that probably doesn't buy you much. I am just
> curious...

As someone who ran into exactly the same issue the other day I'm glad that
people are bothering; it's terribly interesting to read other people's
experiences and suggestions. And, as someone who has been doing that, my
personal response to your point is to wonder if it makes sense to define
something that should be and is constant as something that could be changed.
If source is a form of communication to yourself and other programmers then
doesn't it make sense to define something that is constant as, well, a
constant?

-- 
Dave Pearson
http://www.davep.org/lisp/
From: Pascal Costanza
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c6rq1v$hbs$1@newsreader2.netcologne.de>
Dave Pearson wrote:

> * Pascal Costanza <········@web.de>:
> 
>>Why don't you just use defvar or defparameter when it turns out that
>>defconstant doesn't do the right thing? This looks to me like wasting too
>>much time on something that probably doesn't buy you much. I am just
>>curious... 
> 
> As someone who ran into exactly the same issue the other day I'm glad that
> people are bothering; it's terribly interesting to read other people's
> experiences and suggestions. And, as someone who has been doing that, my
> personal response to your point is to wonder if it makes sense to define
> something that should be and is constant as something that could be changed.
> If source is a form of communication to yourself and other programmers then
> doesn't it make sense to define something that is constant as, well, a
> constant?

Good point.


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.04.29.16.37.19.699160@evaluator.pt>
On Thu, 29 Apr 2004 17:19:13 +0200, Pascal Costanza wrote:

> A meta comment / question:
> 
> Why don't you just use defvar or defparameter when it turns out that
> defconstant doesn't do the right thing? This looks to me like wasting
> too much time on something that probably doesn't buy you much. I am just
> curious...

Maybe because I'm looking for the RightThing (TM).

More seriously, because:

1) Pragmatically speaking, defconstant conveys information to the (human)
   reader that is quite different from what we expect from defvar or
   defparameter.  I think that we should program as literary as possible
   and this means that the forms we use should reflect the intent of the
   programmer.

2) I want to take advantage of the potential error checking that a good
   Common Lisp compiler gives you regarding redefinition of constants
   (think about (setq pi 123)).

3) I want to take advantage of the potential performance gains that a good
   Common Lisp compiler gives you regarding the use of defconstant versus
   defvar or defparameter.

4) I like to learn more about Common Lisp.  I've been using this language
   for more than 15 years and I still learn something new about it almost
   everyweek.  And I like to know that I have still lots of things to
   learn about it for the next decades.

Best regards,

Antonio Leitao.
From: Marco Antoniotti
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <W7Olc.140$a5.42263@typhoon.nyu.edu>
Antonio Menezes Leitao wrote:

> On Thu, 29 Apr 2004 17:19:13 +0200, Pascal Costanza wrote:
> 
> 
>>A meta comment / question:
>>
>>Why don't you just use defvar or defparameter when it turns out that
>>defconstant doesn't do the right thing? This looks to me like wasting
>>too much time on something that probably doesn't buy you much. I am just
>>curious...
> 
> 
> Maybe because I'm looking for the RightThing (TM).

Yes, but in your specific case it'd seem that TART (The Almost Right 
Thing) would be

	(defconstant +foo+ '(nil . nil))

Doesn't this solve most problems? (Modulo treatment of constants in code?)

Cheers

Marco
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.05.04.15.41.52.528677@evaluator.pt>
On Tue, 04 May 2004 10:53:43 -0400, Marco Antoniotti wrote:

> 
> 
> Antonio Menezes Leitao wrote:
> 
>> On Thu, 29 Apr 2004 17:19:13 +0200, Pascal Costanza wrote:
>> 
>> 
>>>A meta comment / question:
>>>
>>>Why don't you just use defvar or defparameter when it turns out that
>>>defconstant doesn't do the right thing? This looks to me like wasting
>>>too much time on something that probably doesn't buy you much. I am just
>>>curious...
>> 
>> 
>> Maybe because I'm looking for the RightThing (TM).
> 
> Yes, but in your specific case it'd seem that TART (The Almost Right 
> Thing) would be
> 
> 	(defconstant +foo+ '(nil . nil))
> 
> Doesn't this solve most problems? (Modulo treatment of constants in code?)

No, because the compiler is free to coalesce similar literals.  So,

(defconstant +foo+ '(nil . nil))

and 

(defconstant +bar+ '(nil . nil))

might make (eq +foo+ +bar+) true.

In my case, I need to be sure that there is no other eq pair in the Lisp
image.

Thanks,

Antonio Leitao.
From: David Steuber
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <87fzaexz0y.fsf@david-steuber.com>
Antonio Menezes Leitao <··············@evaluator.pt> writes:

> > Yes, but in your specific case it'd seem that TART (The Almost Right 
> > Thing) would be
> > 
> > 	(defconstant +foo+ '(nil . nil))
> > 
> > Doesn't this solve most problems? (Modulo treatment of constants in code?)
> 
> No, because the compiler is free to coalesce similar literals.  So,
> 
> (defconstant +foo+ '(nil . nil))
> 
> and 
> 
> (defconstant +bar+ '(nil . nil))
> 
> might make (eq +foo+ +bar+) true.
> 
> In my case, I need to be sure that there is no other eq pair in the Lisp
> image.

Forgive a stupid question, but why is the above a problem?  Do you
have some case where you would want (eq 2 2) to be false?

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.05.06.06.57.20.725508@evaluator.pt>
On Wed, 05 May 2004 22:57:49 +0000, David Steuber wrote:

> Antonio Menezes Leitao <··············@evaluator.pt> writes:
> 
>> > Yes, but in your specific case it'd seem that TART (The Almost Right 
>> > Thing) would be
>> > 
>> > 	(defconstant +foo+ '(nil . nil))
>> > 
>> > Doesn't this solve most problems? (Modulo treatment of constants in code?)
>> 
>> No, because the compiler is free to coalesce similar literals.  So,
>> 
>> (defconstant +foo+ '(nil . nil))
>> 
>> and 
>> 
>> (defconstant +bar+ '(nil . nil))
>> 
>> might make (eq +foo+ +bar+) true.
>> 
>> In my case, I need to be sure that there is no other eq pair in the Lisp
>> image.
> 
> Forgive a stupid question, but why is the above a problem?  Do you
> have some case where you would want (eq 2 2) to be false?

Do you want (eq (cons 1 2) (cons 1 2)) to be true?

The original problem was to define a constant that was a unique pair. 
Being unique was a requirement.

The non-solution presented above demonstrates that I could'n use literal
pairs because the compiler might coalesce them, making my pair non-unique.

Antonio Leitao.
From: Raymond Wiker
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <86hduuq8ii.fsf@raw.grenland.fast.no>
Antonio Menezes Leitao <··············@evaluator.pt> writes:

> On Wed, 05 May 2004 22:57:49 +0000, David Steuber wrote:
>
>> Antonio Menezes Leitao <··············@evaluator.pt> writes:
>> 
>>> > Yes, but in your specific case it'd seem that TART (The Almost Right 
>>> > Thing) would be
>>> > 
>>> > 	(defconstant +foo+ '(nil . nil))
>>> > 
>>> > Doesn't this solve most problems? (Modulo treatment of constants in code?)
>>> 
>>> No, because the compiler is free to coalesce similar literals.  So,
>>> 
>>> (defconstant +foo+ '(nil . nil))
>>> 
>>> and 
>>> 
>>> (defconstant +bar+ '(nil . nil))
>>> 
>>> might make (eq +foo+ +bar+) true.
>>> 
>>> In my case, I need to be sure that there is no other eq pair in the Lisp
>>> image.
>> 
>> Forgive a stupid question, but why is the above a problem?  Do you
>> have some case where you would want (eq 2 2) to be false?
>
> Do you want (eq (cons 1 2) (cons 1 2)) to be true?
>
> The original problem was to define a constant that was a unique pair. 
> Being unique was a requirement.
>
> The non-solution presented above demonstrates that I could'n use literal
> pairs because the compiler might coalesce them, making my pair non-unique.

        Would something like 

(defconstant +foo+ '(#:a . #:b)) 
(defconstant +bar+ '(#:a . #:b))

work?

-- 
Raymond Wiker                        Mail:  ·············@fast.no
Senior Software Engineer             Web:   http://www.fast.no/
Fast Search & Transfer ASA           Phone: +47 23 01 11 60
P.O. Box 1677 Vika                   Fax:   +47 35 54 87 99
NO-0120 Oslo, NORWAY                 Mob:   +47 48 01 11 60

Try FAST Search: http://alltheweb.com/
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.05.06.17.47.38.38685@evaluator.pt>
On Thu, 06 May 2004 10:12:21 +0200, Raymond Wiker wrote:

> Antonio Menezes Leitao <··············@evaluator.pt> writes:
> 
>> On Wed, 05 May 2004 22:57:49 +0000, David Steuber wrote:
>>
>>> Antonio Menezes Leitao <··············@evaluator.pt> writes:
>>> 
>>>> > Yes, but in your specific case it'd seem that TART (The Almost Right 
>>>> > Thing) would be
>>>> > 
>>>> > 	(defconstant +foo+ '(nil . nil))
>>>> > 
>>>> > Doesn't this solve most problems? (Modulo treatment of constants in code?)
>>>> 
>>>> No, because the compiler is free to coalesce similar literals.  So,
>>>> 
>>>> (defconstant +foo+ '(nil . nil))
>>>> 
>>>> and 
>>>> 
>>>> (defconstant +bar+ '(nil . nil))
>>>> 
>>>> might make (eq +foo+ +bar+) true.
>>>> 
>>>> In my case, I need to be sure that there is no other eq pair in the Lisp
>>>> image.
>>> 
>>> Forgive a stupid question, but why is the above a problem?  Do you
>>> have some case where you would want (eq 2 2) to be false?
>>
>> Do you want (eq (cons 1 2) (cons 1 2)) to be true?
>>
>> The original problem was to define a constant that was a unique pair. 
>> Being unique was a requirement.
>>
>> The non-solution presented above demonstrates that I could'n use literal
>> pairs because the compiler might coalesce them, making my pair non-unique.
> 
>         Would something like 
> 
> (defconstant +foo+ '(#:a . #:b)) 
> (defconstant +bar+ '(#:a . #:b))
> 
> work?

Yes. I guess it would.  In this case, the compiler will not be able to
coalesce them.  Unfortunately, my constant needed the NILs.  So the
actual problem might be rephrase like this:

  Define a constant that is a unique pair of empty lists.

This thread is starting to look like a language puzzle.  This kind of
questions is more typical of comp.lang.scheme than comp.lang.lisp :-)

Thanks,

Antonio Leitao.
From: Harald Hanche-Olsen
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pcoy8o5guxr.fsf@shuttle.math.ntnu.no>
+ Antonio Menezes Leitao <··············@evaluator.pt>:

| So the actual problem might be rephrase like this:
| 
|   Define a constant that is a unique pair of empty lists.

Excuse me if I missed something, but isn't this solved rather neatly
by  (defconstant-once +foo+ (cons nil nil))  where DEFCONSTANT-ONCE is
as Thomas Burdick explained elsewhere in this semi-infinite thread?

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.05.06.23.14.27.127421@evaluator.pt>
On Thu, 06 May 2004 22:30:24 +0200, Harald Hanche-Olsen wrote:

> + Antonio Menezes Leitao <··············@evaluator.pt>:
> 
> | So the actual problem might be rephrase like this:
> | 
> |   Define a constant that is a unique pair of empty lists.
> 
> Excuse me if I missed something, but isn't this solved rather neatly
> by  (defconstant-once +foo+ (cons nil nil))  where DEFCONSTANT-ONCE is
> as Thomas Burdick explained elsewhere in this semi-infinite thread?

Yes. I already said that Thomas Burdick solution was perfectly OK and I
even suggest a new FAQ entry for this. However, some Common Lispers seem
to enjoy thinking about other solutions to the same problem that do not
involve 'boundp' calls and they keep suggesting me these other solutions
that, unfortunately, do not solve the original problem. My recent posts in
this thread are just to clarify why those solutions do not work.

I even said in my previous post that this semi-infinite thread now looks
like a programming puzzle more typical of comp.lang.scheme than
comp.lang.lisp. And you and me are just making it even more infinite :-)

Antonio Leitao.
From: Harald Hanche-Olsen
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pcoad0kylt7.fsf@shuttle.math.ntnu.no>
+ Antonio Menezes Leitao <··············@evaluator.pt>:

| And you and me are just making it even more infinite :-)

Well, OK, the infiniter the better.  Wanna go for aleph-1?

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Pascal Costanza
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c7eiqt$8s9$1@newsreader2.netcologne.de>
Antonio Menezes Leitao wrote:

> So the
> actual problem might be rephrase like this:
> 
>   Define a constant that is a unique pair of empty lists.
> 
> This thread is starting to look like a language puzzle.

It seems to me by now that defconstant is simply not well specified. The 
spec says that "the consequences are undefined if an attempt is made 
[...] to assign it to a different value using a subsequent defconstant". 
The glossary entry for "different" gives examples for "different under 
equal", however the text for defconstant suggests that only "different 
under eql" is acceptable.

It might have been a good idea to allow for further specification what 
kind of sameness one wants for a constant, like for other forms in CL. 
Something like this:

(defconstant +foo+ (cons nil nil)
   "documentation" :test #'equal)


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: ·········@random-state.net
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <c6qmvk$8phnu$1@midnight.cs.hut.fi>
Antonio Menezes Leitao <··············@evaluator.pt> wrote:

> (defconstant +foo+ (cons nil nil))

Try:
 
 (defmacro defconst (symbol value &optional doc)
   `(defconstant ,symbol (if (boundp ',symbol)
			     (symbol-value ',symbol)
			     ,value)
     ,@(when doc (list doc))))

Cheers,

 -- Nikodemus
From: Antonio Menezes Leitao
Subject: Re: The Hyperspec and portability between Common Lisp compilers (long)
Date: 
Message-ID: <pan.2004.04.29.14.43.05.510326@evaluator.pt>
On Thu, 29 Apr 2004 10:55:48 +0000, nikodemus wrote:

> Antonio Menezes Leitao <··············@evaluator.pt> wrote:
> 
>> (defconstant +foo+ (cons nil nil))
> 
> Try:
>  
>  (defmacro defconst (symbol value &optional doc)
>    `(defconstant ,symbol (if (boundp ',symbol)
> 			     (symbol-value ',symbol)
> 			     ,value)
>      ,@(when doc (list doc))))
> 
> Cheers,
> 
>  -- Nikodemus

That's the same solution I got after thinking about Paul Dietz suggestion.
I think it solves the problem.

I guess we need another entry in the FAQ.

Thanks a lot.

Antonio Leitao.