From: Adam Warner
Subject: STRING=
Date: 
Message-ID: <pan.2003.06.14.01.53.33.309186@consulting.net.nz>
Hands up who have been programming in ANSI Common Lisp for at least a year
but didn't realise that all of these are valid expressions and they return
NIL or T as set out below:

(a) (string= "string" nil) => nil
(b) (string= "T" t) => t
(c) (string= "NIL" nil) => t
(d) (string= "STRING" 'string) => t
(e) (string= #\A 'a) => t

Perhaps you too were under the mistaken impression that STRING= had to be
supplied with strings (and comparing a string and a symbol would be an
error)? STRING= accepts string designators, which include "a symbol
(denoting the string that is its name)". Characters are also string
designators "(denoting a singleton string that has the character as its
only element)". Thus STRING= accepts some arguments that are STRINGP
false.

[Note that the same reasoning doesn't appear to apply to CHAR=, which
doesn't employ the notion of a character _designator_. However it appears
CMUCL allows this expression regardless: (char= #\a nil). It appears CLISP
is correct in flagging this as an error. Does anyone know which operators
employ character designators?]

So when one is comparing symbol values that contain strings or NIL (where
nil is used to denote an empty string) then the appropriate equality
operator is EQUAL. Otherwise one could eventually compare an empty symbol
value with the string "NIL" and end up with true when wanting false.

Comparison of string designators is likely to be common (since the string
comparison operators are commonly used). This means non-ANSI compliant
readtable case modes like the so-called "modern mode" introduce more
fundamental differences in semantics than I had previously expected.

Regards,
Adam

From: Lars Brinkhoff
Subject: Re: STRING=
Date: 
Message-ID: <85n0gl3z18.fsf@junk.nocrew.org>
See also STRING, which resolves string designators into strings.

See also:
bounding index designator,
character designator,
class designator,
condition designator,
extended function designator,
external file format designator,
file position designator,
function designator,
interval designator,
list designator,
logical host designator,
package designator,
pathname designator,
readtable designator,
restart designator,
spreadable argument list designator,
stream designator,
stream variable designator,
string designator.
From: Kent M Pitman
Subject: Re: STRING=
Date: 
Message-ID: <sfwvfv8fves.fsf@shell01.TheWorld.com>
Lars Brinkhoff <·········@nocrew.org> writes:

> See also STRING, which resolves string designators into strings.
> 
> See also:
> bounding index designator,
> character designator,
> class designator,
> condition designator,  [...]

And 1.4.1.5 Designators

http://www.lispworks.com/reference/HyperSpec/Body/01_dae.htm
From: Rob Warnock
Subject: Re: STRING=
Date: 
Message-ID: <zfycnccXwOjtzXGjXTWc-w@speakeasy.net>
Kent M Pitman  <······@world.std.com> wrote:
+---------------
| And 1.4.1.5 Designators
| http://www.lispworks.com/reference/HyperSpec/Body/01_dae.htm
+---------------

This brings up something that I've always wondered about. 1.4.1.5 says:

	For example, ``nil'' and ``the value of *standard-output*''
	are operationally indistinguishable as stream designators.

And indeed, the Glossary entry says:

	stream designator n. a designator for a stream; that is, an
	object that denotes a stream and that is one of: t (denoting
	the value of *terminal-io*), nil (denoting the value of
	*standard-input* for input stream designators or denoting
	the value of *standard-output* for output stream designators),
	or a stream (denoting itself). 

So why does FORMAT -- apparently uniquely among output functions --
interpret NIL and T as destinations differently than the normal convention
for stream designators? Mere convenience? (...and historical compatibility
too, I'm guessing.)

I'm not really complaining, just asking. Certainly this:

	(format nil "blah, blah ~S ~S~%" foo bar)

is more convenient than this:

	(with-output-to-string (s)
	  (format s "blah, blah ~S ~S~%" foo bar))

But was that the only reason, convenience?


-Rob

-----
Rob Warnock, PP-ASEL-IA		<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Kent M Pitman
Subject: Re: STRING=
Date: 
Message-ID: <sfwbrwygssq.fsf@shell01.TheWorld.com>
····@rpw3.org (Rob Warnock) writes:

> So why does FORMAT -- apparently uniquely among output functions --
> interpret NIL and T as destinations differently than the normal convention
> for stream designators? Mere convenience? (...and historical compatibility
> too, I'm guessing.)

Because it had the special need to create strings, and one of NIL and T
"had to be" sacrificed.  The logical one was NIL, meaning "don't output".
T was left to use, and *terminal-io* is something one almost never does 
output to, so it was assigned to *standard-output*.

(PRIN1 and friends mostly could not create strings because they made so 
little output as individuals that it wouldn't be useful.  You'd have been
string-concatenating all over the place.  And also, in one of the two major
venues available to program at that time, there was not even a string
datatype--we only had symbols.)

Remember that all of this was long before there was any language regularity.
It was at the time people were just hoking things together.  The whole T/NIL
thing for "streams" (and there were barely even streams at the time) was
all shrouded in mystery due to poor documentaiton at the time.
From: Adam Warner
Subject: Re: STRING=
Date: 
Message-ID: <pan.2003.06.14.23.34.01.729186@consulting.net.nz>
Hi Kent M Pitman,

> And 1.4.1.5 Designators
> 
> http://www.lispworks.com/reference/HyperSpec/Body/01_dae.htm

A most helpful subsection, thanks Kent.

Regards,
Adam
From: Joerg-Cyril Hoehle
Subject: Re: STRING=
Date: 
Message-ID: <u65l9vmvm.fsf@T-Systems.com>
Adam Warner <······@consulting.net.nz> writes:
> [Note that the same reasoning doesn't appear to apply to CHAR=, which
> doesn't employ the notion of a character _designator_. However it appears
> CMUCL allows this expression regardless: (char= #\a nil). It appears CLISP
> is correct in flagging this as an error. Does anyone know which operators
> employ character designators?]
Hi,

I claim that CLISP is not incorrect.
(char= #\a nil) is non-portable, because nil is not a character. It's
not even a character designator.

CHAR= is specified to operate on characters, not character
designators, as you note.

nil is not a character designator because it's not a designator for a
string of length 1. The length is 3.

(char= #\a nil) being non portable, any implementation may choose to
behave any way it wishes, from what I understood of the CLHS. CLISP is
known for being strict and throwing errors. CMUCL behaves differently
here.

From what I understood of what Kent Pitman said here and there, no
notice in "Exceptional Situations" about wrong types does not mean that
no exception can be raised about wrong types.

BTW, thanks for your various postings.

Regards,
	Joerg Hoehle
TSI ITC-Security Technologiezentrum