Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Read #<>

21 views
Skip to first unread message

ing...@gmail.com

unread,
Mar 5, 2007, 3:12:21 AM3/5/07
to
Hi,

Is it possible to read a list with #<> objects in it, with the
function read? If not, is there an other function I can use?

Thanks

Willem Broekema

unread,
Mar 5, 2007, 4:44:37 AM3/5/07
to
On Mar 5, 9:12 am, inge...@gmail.com wrote:
> Is it possible to read a list with #<> objects in it, with the
> function read? If not, is there an other function I can use?

Nope, by definition printed representations starting with #< are not
able to be read in again. The character "#" is a special character for
the reader, and the character after it, "<", determines that the
reader should signal an error. See CLHS 2.4.8.20 "Sharpsign Less-Than-
Sign". (I think it's really neat and elegant how macro characters
work.)

You may be able to obtain a readable representation by binding *print-
readably* to true during the printing. But this will only have effect
if the function that does the printing takes that variable into
account, of course.

Otherwise, if a readable representation makes sense for the object
(reading the representation in should lead to an object that is
somehow "similar" to the printed object, where "similar" can not be
further defined) you can (re)define a method for 'print-object. That
method could take the value of *print-readably* into account, e.g.
give a short #<..> representation if the value is false, and otherwise
give a longer but readable representation.

- Willem

Tim Bradshaw

unread,
Mar 5, 2007, 6:58:00 AM3/5/07
to

What you say in the parts I deleted is essentially correct: in
particular, as you say, things that print #<...> are intended to *not*
be readable.

However it's worth noting that *PRINT-READABLY* is not optional: if it
is true, then anything that prints *must* either print in such a way
that it can be read back, or must signal an error of type PRINT-NOT-
READABLE. So if you bind *PRINT-READABLY* to true before doing any
printing you should be assured that nothing gets printed as #<...>.

Of course lots of print methods probably do not ensure this, which is
a shame. PRINT-UNREADABLE-OBJECT can help a lot in the implementation
of such methods.

--tim

Tayssir John Gabbour

unread,
Mar 5, 2007, 12:18:20 PM3/5/07
to
On Mar 5, 9:12 am, inge...@gmail.com wrote:
> Is it possible to read a list with #<> objects in it, with the
> function read? If not, is there an other function I can use?

BTW, if you're asking "I've got a file with #<...> in it, and I just
need to read the damn file in somehow, ignoring the #<...>'s!" like I
once did, note that you can redefine #< like:

(let ((*readtable* (copy-readtable)))
(set-dispatch-macro-character #\# #\< #'|#<-reader|)
;; Example:
(read-from-string "#<BUILT-IN-CLASS FIXNUM>"))

where you define the oddly-named function |#<-reader| perhaps
something like:

(defun |#<-reader| (stream char arg)
(declare (ignore char arg))
...)

The function name uses vertical bars | so you can use the weird #<
characters in its name.


Tayssir

Richard M Kreuter

unread,
Mar 5, 2007, 3:00:33 PM3/5/07
to

But how should #<-reader work? Any arbitrarily unparseable text can
occur after a sharp-less-than. For instance, if #<-reader just scans
forward for the first greater-than, it'd fail on the (unreadable)
printed representation of some instances of this class:

(defclass thing-with-string ()
((string :initarg :string :accessor string-of)))

(defmethod print-object ((object thing-with-string) stream)
(print-unreadable-object (object stream :type t :identity t)
(princ (string-of object) stream)))

(print (make-instance 'thing-with-string :string "<foo>"))
-| #<THING-WITH-STRING <foo> {51769DB9}>

--
RmK

Tim Bradshaw

unread,
Mar 5, 2007, 3:18:16 PM3/5/07
to
On 2007-03-05 20:00:33 +0000, Richard M Kreuter <kre...@progn.net> said:

> But how should #<-reader work? Any arbitrarily unparseable text can
> occur after a sharp-less-than.

Presumably the author would have looked at what they need to parse in
this case, without trying to solve the general problem...

Tayssir John Gabbour

unread,
Mar 5, 2007, 3:40:28 PM3/5/07
to
On Mar 5, 9:00 pm, Richard M Kreuter <kreu...@progn.net> wrote:

> "Tayssir John Gabbour" <tayssir.j...@googlemail.com> writes:
> > BTW, if you're asking "I've got a file with #<...> in it, and I just
> > need to read the damn file in somehow, ignoring the #<...>'s!" like I
> > once did, note that you can redefine #< like:
>
> But how should #<-reader work? Any arbitrarily unparseable text can
> occur after a sharp-less-than. For instance, if #<-reader just scans
> forward for the first greater-than, it'd fail on the (unreadable)
> printed representation of some instances of this class:

That's why I didn't specify it. ;) I didn't know what the fellow's
situation was. Typically, one hopes the 80% solution Just Works, and
if not, manual adjustments may follow.

I was fortunately able to get away with read-delimited-list. Then I
fixed the situation in a more permanent way.


Tayssir

Barry Margolin

unread,
Mar 5, 2007, 9:06:35 PM3/5/07
to
In article <1173095880....@v33g2000cwv.googlegroups.com>,
"Tim Bradshaw" <tfb+g...@tfeb.org> wrote:

> On Mar 5, 9:44 am, "Willem Broekema" <metaw...@gmail.com> wrote:
> > On Mar 5, 9:12 am, inge...@gmail.com wrote:
>
> >
> > Otherwise, if a readable representation makes sense for the object
> > (reading the representation in should lead to an object that is
> > somehow "similar" to the printed object, where "similar" can not be
> > further defined) you can (re)define a method for 'print-object. That
> > method could take the value of *print-readably* into account, e.g.
> > give a short #<..> representation if the value is false, and otherwise
> > give a longer but readable representation.
>
> What you say in the parts I deleted is essentially correct: in
> particular, as you say, things that print #<...> are intended to *not*
> be readable.

Yes. That's the printed representation used for types that don't have a
good way to recreate themselves from a printed representation. Also,
when *PRINT-READABLY* is false, it may be used by some types that
*could* be read, but for which this is usually unnecessary. For
instance, while it would be possible to design a readable printed
representation for hash tables, the language doesn't require it; an
implementation might go beyond the call of duty and use an extension
when *PRINT-READABLY* is true, but otherwise use #<HASH-TABLE ...>.

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***

Richard M Kreuter

unread,
Mar 5, 2007, 9:32:33 PM3/5/07
to
"Tim Bradshaw" <tfb+g...@tfeb.org> writes:

> ...it's worth noting that *PRINT-READABLY* is not optional: if it is


> true, then anything that prints *must* either print in such a way
> that it can be read back, or must signal an error of type PRINT-NOT-
> READABLE. So if you bind *PRINT-READABLY* to true before doing any
> printing you should be assured that nothing gets printed as #<...>.

So how /do/ you print something readably in PRINT-OBJECT? The only
approach I can think of is to use sharp-dot, and then only when
*READ-EVAL* is true.

Specifically, if a PRINT-OBJECT method emits anything for an object
that doesn't have a standard read syntax, then a standard Lisp reader
won't be able to parse it. But since most things that you'll want to
write PRINT-OBJECT methods for won't have a read syntax, all you'll be
able to do is print "#.(make-thing ...)", if "readably" means
"readable in the I/O syntax established by WITH-STANDARD-IO-SYNTAX",
which I think it's supposed to (otherwise, for instance, the examples
in the WITH-STANDARD-IO-SYNTAX entry won't work, in general).

Is this right?

--
RmK

Tayssir John Gabbour

unread,
Mar 5, 2007, 11:18:41 PM3/5/07
to
On Mar 6, 3:32 am, Richard M Kreuter <kreu...@progn.net> wrote:
> So how /do/ you print something readably in PRINT-OBJECT? The only
> approach I can think of is to use sharp-dot, and then only when
> *READ-EVAL* is true.

You might like Arthur Lemmens' presentation he gave in Cologne, about
various object persistence methods, including print-object...
<http://www.pentaside.org/paper/persistence-lemmens.txt>

This can incidentally be seen in light of his more recent Rucksack
persistence library...


Tayssir

Takehiko Abe

unread,
Mar 5, 2007, 11:32:52 PM3/5/07
to
Richard M Kreuter wrote:

> > ...it's worth noting that *PRINT-READABLY* is not optional: if it is
> > true, then anything that prints *must* either print in such a way
> > that it can be read back, or must signal an error of type PRINT-NOT-
> > READABLE. So if you bind *PRINT-READABLY* to true before doing any
> > printing you should be assured that nothing gets printed as #<...>.
>
> So how /do/ you print something readably in PRINT-OBJECT? The only
> approach I can think of is to use sharp-dot, and then only when
> *READ-EVAL* is true.

The easy way out is to call-next-method. (it will probably signal
error.)

Tim Bradshaw

unread,
Mar 6, 2007, 2:14:16 AM3/6/07
to
On 2007-03-06 02:32:33 +0000, Richard M Kreuter <kre...@progn.net> said:

> So how /do/ you print something readably in PRINT-OBJECT? The only
> approach I can think of is to use sharp-dot, and then only when
> *READ-EVAL* is true.

I think it would be reasonable to assume that you're allowed to make
use of read macros that you've provided. But yes, that's probably
something that ought to be explicit in the standard I think.

--tim

Pascal Bourguignon

unread,
Mar 6, 2007, 5:14:39 AM3/6/07
to
ing...@gmail.com writes:
> Is it possible to read a list with #<> objects in it, with the
> function read? If not, is there an other function I can use?

Not with the standard dispatch reader macro for #<.

If you've got some text including #<> objects, that you need to read
back, you can do it, writting your own reader macro for #<, but in
general you won't be able to build back equivalent objects.

Then, you have to write some parser for the text between < and >.
For example, you may have some > escaped into strings or otherwise.
Or perhaps not. It'd be perfectly expectable to have something like:

(1 2 #< some > strange > and > unreadable > object > 4 5)

(even if no sane programmer would write such a print-object method...)
So you need to know your unreadable objects, and how to parse them.

Assuming that the syntax you want to read is (regexp): #<[^>]*>
you could write:

(defclass unreadable-object ()
((text :initarg :text :accessor unreadable-object-text)))

(defmethod print-object ((self unreadable-object) stream)
"To ensure that unreadable objects are printed as they are read ;-)"
(print-unreadable-object (self stream :type nil :identity nil)
(princ (unreadable-object-text self) stream)))

(defun my-#<-reader (stream sub-char arg)
(declare (ignore sub-char arg))
(loop :with buffer = (make-array 0 :adjustable t :fill-pointer 0
:element-type 'character)
:for ch = (read-char stream t nil t)
:until (char= #\> ch)
:do (vector-push-extend ch buffer)
:finally (return (make-instance 'unreadable-object :text buffer))))

(defparameter *my-readtable* (copy-readtable nil))

(SET-DISPATCH-MACRO-CHARACTER #\# #\< (function my-#<-reader) *my-readtable*)


(let ((*readtable* *my-readtable*))
(read-from-string "(1 2 #<some unreadable object> 4 5)"))

--> (1 2 #<some unreadable object> 4 5) ;
35

--
__Pascal Bourguignon__ http://www.informatimago.com/
Un chat errant
se soulage
dans le jardin d'hiver
Shiki

Richard M Kreuter

unread,
Mar 6, 2007, 9:05:59 AM3/6/07
to
Tim Bradshaw <t...@tfeb.org> writes:

> On 2007-03-06 02:32:33 +0000, Richard M Kreuter <kre...@progn.net> said:
>
>> So how /do/ you print something readably in PRINT-OBJECT? The only
>> approach I can think of is to use sharp-dot, and then only when
>> *READ-EVAL* is true.
>
> I think it would be reasonable to assume that you're allowed to make
> use of read macros that you've provided.

But then how can WITH-STANDARD-IO-SYNTAX work, in general?

Here's the CLHS example of WITH-STANDARD-IO-SYNTAX:

| (with-open-file (file pathname :direction :output)
| (with-standard-io-syntax
| (print data file)))
|
| ;;; ... Later, in another Lisp:
|
| (with-open-file (file pathname :direction :input)
| (with-standard-io-syntax
| (setq data (read file))))

If the PRINT emits output with a custom read macro, then the READ will
error, since WITH-STANDARD-IO-SYNTAX uses the standard readtable.

--
RmK

Vassil Nikolov

unread,
Mar 6, 2007, 8:54:26 PM3/6/07
to

On Tue, 06 Mar 2007 09:05:59 -0500, Richard M Kreuter <kre...@progn.net> said:
| But then how can WITH-STANDARD-IO-SYNTAX work, in general?

Here is a hack or a kludge (depending on what is better, I guess...):

> (defstruct foo bar baz)
FOO
> (defun make-foo (&rest args) `(the real foo ,@args)) ;call the real constructor here
MAKE-FOO
> '#s(foo :bar 1 :baz 2)
(THE REAL FOO :BAR 1 :BAZ 2)

and then the printer for real foos emits #S syntax. (Determining the
legality of the above is left as an exercise for the reader).

---Vassil.


--
Is your code free of side defects?

Richard M Kreuter

unread,
Mar 7, 2007, 12:10:43 AM3/7/07
to
Vassil Nikolov <vnikolo...@pobox.com> writes:

That's as clever as it is gross.

Anyhow, even if that works somewhere, couldn't an implementation
notice that you're redefining MAKE-FOO such that it's no longer a
constructor function for FOO-type structures? This could suffice to
make sharpsign-S not apply since that sharpsign-S

| is valid only if NAME is the name of a structure type already
| defined by ‘defstruct’ and if the structure type has a standard
| constructor function.

--
RmK

Rob Warnock

unread,
Mar 7, 2007, 1:13:27 AM3/7/07
to
Richard M Kreuter <kre...@progn.net> wrote:
+---------------

| Tim Bradshaw <t...@tfeb.org> writes:
| > Richard M Kreuter <kre...@progn.net> said:
| >
| >> So how /do/ you print something readably in PRINT-OBJECT? The only
| >> approach I can think of is to use sharp-dot, and then only when
| >> *READ-EVAL* is true.
| >
| > I think it would be reasonable to assume that you're allowed to make
| > use of read macros that you've provided.
|
| But then how can WITH-STANDARD-IO-SYNTAX work, in general?
+---------------

It can't. If you insist on using WITH-STANDARD-IO-SYNTAX then
there *will* be lots of objects you can't externalize.


-Rob

-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

Tim Bradshaw

unread,
Mar 7, 2007, 2:34:14 AM3/7/07
to
On 2007-03-06 14:05:59 +0000, Richard M Kreuter <kre...@progn.net> said:

> If the PRINT emits output with a custom read macro, then the READ will
> error, since WITH-STANDARD-IO-SYNTAX uses the standard readtable.

Yes. If you want a special readtable in place but otherwise want to be
assured of standard syntax you need to put stuff inside
WITH-STANDARD-IO-SYNTAX to make that be the case.


Pascal Bourguignon

unread,
Mar 7, 2007, 3:52:02 AM3/7/07
to
Richard M Kreuter <kre...@progn.net> writes:

> Vassil Nikolov <vnikolo...@pobox.com> writes:
>
>> On Tue, 06 Mar 2007 09:05:59 -0500, Richard M Kreuter <kre...@progn.net> said:
>> | But then how can WITH-STANDARD-IO-SYNTAX work, in general?
>>
>> Here is a hack or a kludge (depending on what is better, I guess...):
>>
>> > (defstruct foo bar baz)
>> FOO
>> > (defun make-foo (&rest args) `(the real foo ,@args)) ;call the real constructor here
>> MAKE-FOO
>> > '#s(foo :bar 1 :baz 2)
>> (THE REAL FOO :BAR 1 :BAZ 2)
>>
>> and then the printer for real foos emits #S syntax. (Determining the
>> legality of the above is left as an exercise for the reader).
>
> That's as clever as it is gross.
>
> Anyhow, even if that works somewhere, couldn't an implementation
> notice that you're redefining MAKE-FOO such that it's no longer a
> constructor function for FOO-type structures? This could suffice to
> make sharpsign-S not apply since that sharpsign-S

Well, the specification of #S doesn't really insist on a structure,
only on a "constructor" function. I think the above is compliant.

Vassil Nikolov

unread,
Mar 7, 2007, 7:37:47 AM3/7/07
to

| | defined by DEFSTRUCT and if the structure type has a standard
| | constructor function.

It shouldn't since the constructor function is invoked by _name_:
``#S(<structure name> ...)'' is defined to be equivalent to
``#.(<constructor function name> ...)'' (except that presumably
*READ-EVAL* does not apply), see the first paragraph of [1] for
the exact wording. (In the previous sentence, "it" refers to
what could make #S not apply.)

Of course, this is not all plain sailing. For example, one
would want to (DECLAIM (NOTINLINE <constructor function name>))
along with redefining it.

Obviously, from a purist's point of view, this is not standard
I/O syntax (and if one wants to redefine/extend the latter, one
would have to redefine/extend the standard...), or rather this
is an abuse of standard I/O syntax. On the other hand, we are
arguably still reading structures here, albeit in the abstract
sense of the word (rather than in the concrete sense of
instances of instances of STRUCTURE-CLASS). I suppose the
court's decision would depend on who exactly the judges are,
as in many other matters...

[1] http://www.lisp.org/HyperSpec/Body/sec_2-4-8-13.html

Richard M Kreuter

unread,
Mar 7, 2007, 1:03:26 PM3/7/07
to

Well sure, you can use WITH-STANDARD-IO-SYNTAX as a base on which to
build custom I/O syntaxes.

I was looking that the examples in the WITH-STANDARD-IO-SYNTAX
dictionary entry as constraints on what PRINT-OBJECT methods can do,
since the examples won't work in general if PRINT-OBJECT methods can
emit arbitrary output,

Now that I look at it, the dictionary entry for *PRINT-READABLY* is
clear enough on its own:

| If ‘*print-readably*’ is true, some special rules for printing
| objects go into effect. Specifically, printing any object O₁
| produces a printed representation that, when seen by the Lisp reader
| while the standard readtable is in effect, will produce an object O₂
| that is similar to O₁.

So a PRINT-OBJECT method /must not/ emit anything unreadable in the
standard syntax when *PRINT-READABLY* is true. Provided that all
methods PRINT-OBJECT conform to this protocol WITH-STANDARD-IO-SYNTAX
turns out to be reliable, after all.

--
RmK

Tim Bradshaw

unread,
Mar 7, 2007, 2:47:32 PM3/7/07
to
On 2007-03-07 18:03:26 +0000, Richard M Kreuter <kre...@progn.net> said:

> So a PRINT-OBJECT method /must not/ emit anything unreadable in the
> standard syntax when *PRINT-READABLY* is true. Provided that all
> methods PRINT-OBJECT conform to this protocol WITH-STANDARD-IO-SYNTAX
> turns out to be reliable, after all.

I think that's just clearly a bug in the standard.

Vassil Nikolov

unread,
Mar 7, 2007, 11:37:06 PM3/7/07
to

On Wed, 07 Mar 2007 13:03:26 -0500, Richard M Kreuter <kre...@progn.net> said:
| ...

| | If *print-readably* is true, some special rules for printing
| | objects go into effect. Specifically, printing any object O_1

| | produces a printed representation that, when seen by the Lisp reader
| | while the standard readtable is in effect, will produce an object O_2
| | that is similar to O_1.

| So a PRINT-OBJECT method /must not/ emit anything unreadable in the
| standard syntax when *PRINT-READABLY* is true. Provided that all
| methods PRINT-OBJECT conform to this protocol WITH-STANDARD-IO-SYNTAX
| turns out to be reliable, after all.

Hmmm... So one wonders if "the standard readtable is in effect" even
when *READ-EVAL* is false...

Richard M Kreuter

unread,
Mar 8, 2007, 10:09:15 PM3/8/07
to
Vassil Nikolov <vnikolo...@pobox.com> writes:
> On Wed, 07 Mar 2007 13:03:26 -0500, Richard M Kreuter <kre...@progn.net> said:
> | ...
> | | If *print-readably* is true, some special rules for printing
> | | objects go into effect. Specifically, printing any object O_1
> | | produces a printed representation that, when seen by the Lisp
> | | reader while the standard readtable is in effect, will produce
> | | an object O_2 that is similar to O_1.
>
> | So a PRINT-OBJECT method /must not/ emit anything unreadable in
> | the standard syntax when *PRINT-READABLY* is true.
>
> Hmmm... So one wonders if "the standard readtable is in effect" even
> when *READ-EVAL* is false...

*READ-EVAL* is defined as having an effect on the reader macro
associated with sharp-dot in the standard readtable, not on the
readtable, so I don't see there being a conflict here.

--
RmK


Richard M Kreuter

unread,
Mar 8, 2007, 10:45:32 PM3/8/07
to
Tim Bradshaw <t...@tfeb.org> writes:

Howcome?

It doesn't seem like a bug to me, but I think I can imagine an
argument as to how it could be.

The writeup of the DATA-IO issue that added *PRINT-READABLY*,
PRINT-UNREADABLE-OBJECT, WITH-STANDARD-IO-SYNTAX, PRINT-NOT-READABLE
and *READ-EVAL* says that the aim was to have a way to pass printed
representations between two different programs, possibly on different
implementations [1]. Restricting PRINT-OBJECT methods to the standard
syntax would be consistent with that goal, so that programs could
communicate without needing to negotiate syntaxes.

But maybe you're thinking that the standard syntax already requires
the reading side to be coordinated with the writing side, because, for
example, sharp-s doesn't work unless the reading side has suitably
named structure types, sharp-p may emit notation involving namestrings
that the reading side can't parse, sharp-backslash might name
characters the reading side doesn't support or has a different a name
for, and so forth [2]. Thus the goal of DATA-IO is already
unachievable, and so allowing the writing side to use other syntax
that forces coordination on the reading side doesn't make anything
worse.

Is that the idea?

--
RmK


[1] http://www.lisp.org/HyperSpec/Issues/iss089-writeup.html

[2] Worse, there's nothing user code can do to work around pathname
and character name notation limitations.

Tim Bradshaw

unread,
Mar 9, 2007, 5:33:47 AM3/9/07
to
On Mar 9, 3:45 am, Richard M Kreuter <kreu...@progn.net> wrote:

> > I think that's just clearly a bug in the standard.
>
> Howcome?
>

Because if *PRINT-READABLY* means `only work for the standard
readtable' then there is essentially no way of mandating that an
object for which a non-standard read-syntax has been defined should be
printed readably.

In particular if *PRINT-READABLY* means what it means in your reading
of the standard (which I think is correct) then I think the following
ensues.

If it is true then
- objects for which there is a standard read syntax *must* print
readably;
- objects for which there is not a standard read syntax *must* signal
an error when printed.

if it is false then
- objects for which there is a standard read syntax may not print
readably;
- objects for which there is not a standard read syntax may not print
readably.

So now I'm stuck.

I think what is needed is a pair of variables:

*PRINT-READABLY* means "print as readably as you can possibly making
optimistic assumptions about the readtable"

*PRINT-PORTABLY* means "if *print-readably* is true then you must
signal an error if you can not be read in the standard CL readtable"

That's not nearly precise enough, but I hope you see what I mean.

Absent the second variable I think it is reasonable for a print method
to assume it is false.


Tim Bradshaw

unread,
Mar 9, 2007, 6:40:06 AM3/9/07
to
On Mar 9, 10:33 am, "Tim Bradshaw" <tfb+goo...@tfeb.org> wrote:

> [.. ] may not [...]

Modal verbs are a pig. What I meant is `do not have to' not `must
not'

sorry

Vassil Nikolov

unread,
Mar 10, 2007, 1:11:26 AM3/10/07
to

On 9 Mar 2007 02:33:47 -0800, "Tim Bradshaw" <tfb+g...@tfeb.org> said:

| On Mar 9, 3:45 am, Richard M Kreuter <kreu...@progn.net> wrote:
|| > I think that's just clearly a bug in the standard.
||
|| Howcome?
||

| Because if *PRINT-READABLY* means `only work for the standard
| readtable' then there is essentially no way of mandating that an
| object for which a non-standard read-syntax has been defined should be
| printed readably.

But with #. pretty much any object can be printed readably (at the
cost of implementing suitable constructors, of course), _if_
*READ-EVAL* can be assumed to be true, and I think that is the big "if".

Tim Bradshaw

unread,
Mar 10, 2007, 5:36:44 PM3/10/07
to
On 2007-03-10 06:11:26 +0000, Vassil Nikolov <vnikolo...@pobox.com> said:

> But with #. pretty much any object can be printed readably (at the
> cost of implementing suitable constructors, of course), _if_
> *READ-EVAL* can be assumed to be true, and I think that is the big "if".

It is an enormous assumption: if the only way of reliably printing
readably is to allow completely uncontrolled behaviour from the reader,
then that's also a (disastrous) bug in the standard.

--tim

Vassil Nikolov

unread,
Mar 10, 2007, 7:16:33 PM3/10/07
to

It wasn't a conflict I was thinking about, but I should have read
the CLHS more carefully earlier:

If *READ-EVAL* is false and *PRINT-READABLY* is true, any such
method that would output a reference to the ``#.'' reader macro will
either output something else or will signal an error (as described
above).^1

That still leaves us rather constrained with regards to objects for
which there is a readable printed representation but one that needs
a readtable different from the standard one.

^1 http://www.lisp.org/HyperSpec/Body/var_stprint-readablyst.html
(last sentence of the description)

Richard M Kreuter

unread,
Mar 11, 2007, 7:07:15 PM3/11/07
to
"Tim Bradshaw" <tfb+g...@tfeb.org> writes:
> On Mar 9, 3:45 am, Richard M Kreuter <kreu...@progn.net> wrote:
>> "Tim Bradshaw" <tfb+g...@tfeb.org> writes:
>>>
>>> I think that's just clearly a bug in the standard.
>>
>> Howcome?
>
> Because if *PRINT-READABLY* means `only work for the standard
> readtable' then there is essentially no way of mandating that an
> object for which a non-standard read-syntax has been defined should
> be printed readably.

Yes, there'd be no standard interface for forcing a non-standard
syntax, but I don't think this is too severe a limitation.
Explanation below.

> In particular if *PRINT-READABLY* means what it means in your reading
> of the standard (which I think is correct) then I think the following
> ensues.
>
> If it is true then
> - objects for which there is a standard read syntax *must* print
> readably;
> - objects for which there is not a standard read syntax *must* signal
> an error when printed.
>
> if it is false then
> - objects for which there is a standard read syntax may not print
> readably;
> - objects for which there is not a standard read syntax may not print
> readably.

<inserted from followup email>


> > [.. ] may not [...]
>
> Modal verbs are a pig. What I meant is `do not have to' not `must
> not'

<end inserted followup>


>
> So now I'm stuck.

I don't think you're unstickably stuck. Explanation below.

> I think what is needed is a pair of variables:
>
> *PRINT-READABLY* means "print as readably as you can possibly making
> optimistic assumptions about the readtable"
>
> *PRINT-PORTABLY* means "if *print-readably* is true then you must
> signal an error if you can not be read in the standard CL readtable"
>
> That's not nearly precise enough, but I hope you see what I mean.

I get the distinction you're making.

If we're discussing this as an interpretation of the current standard,
ISTM that the *PRINT-READABLY* in the standard is supposed to mean
what your *PRINT-PORTABLY* does, though I think I can see why no
implementation constrains itself this way: the standard defines the
term "the standard readtable" in a way that makes every occurrence of
the term ambiguous.

If we're discussing this as a matter along the lines of "what should
the next standard look like", then probably specifying a variable that
means what your *PRINT-PORTABLY* does would be useful, for the reasons
described in the DATA-IO writeup. (Actually for maximal usefulness,
such a variable should also prevent implementations from printing any
instance of a standard type that lacks a standard read syntax while
the variable is true.) Whether getting such a variable involves a
clarification/restriction of the existing *PRINT-READABLY* or adding a
new variable is a minor and essentially political point, IMO, so long
as WITH-STANDARD-IO-SYNTAX binds whichever variable it is to true, and
authors of PRINT-OBJECT are informed that their methods must not emit
non-standard syntax while the variable is true.

If we're discussing "what should a CL-like language, not necessarily
CL as it is now, be like", then I'd say that while your
*PRINT-PORTABLY* would be pretty handy for portability, your
*PRINT-READABLY* doesn't need to be in such a language. Here's why:
there are lots of ways to print Lisp objects parseably but
non-portably, so what's the point of having exactly one variable that
means "you may print non-standardly, so long as the output can be
parsed under some unknown circumstances"? More to the point, why not
leave it to people who want non-standard syntaxes to devise their own
protocols to arrange for it, given that they can already do so in CL?

Here's that explanation I've been promising: what do you lose if you
haven't got a variable that means what your *PRINT-READABLY* means?
In CL as it is, you can't force a printed representation for a
standard type that lacks a standard read syntax; whether and how you
can print such things this is up to your implementation. So those
half dozen or so types are off the table. For all other user-defined
types, the authors of those types can define their own variables to
force printing instance of their types in a parseable notation. While
it would perhaps be impractical to hope that independent authors might
agree on non-standard protocols for printing parseably but
non-portably, if you need to integrate code from such authors, you'll
need to ensure that their I/O notations don't conflict whether there's
one *PRINT-READABLY* variable, or as many printer control variables as
user-defined print/read syntaxes. So it's not clear to me that such a
*PRINT-READABLY* variable is all that useful.

Further, even if you have such a *PRINT-READABLY*, you could only take
advantage of non-portable printed representations in case you had
advance knowledge of or control over the program that will do the
reading. If both the printing program and reading program are under
your control (up to what can be done portably), then you can can
define your own printer control variables on one side and read macros
on the other side. If the reading side isn't under your control but
you happen to know that it reads with *READ-EVAL* true, then you can
achieve any effect you want (up to what can be done portably). OTOH,
if you have neither knowledge of nor control over the reading program,
then you ought not to be binding your *PRINT-READABLY* to true in any
case, /and/ ought to be binding a *PRINT-PORTABLY* to true (and maybe
*READ-EVAL* to false).

As I said, this is academic. As things are, no implementation
restricts itself to printing portably when *PRINT-READABLY* is true
(sample below).

--
Richard

All implementations I've tried print all of the following non-standard
objects in this program:

(let* ((*print-readably* t)
(char #\gs) ;a non-standard character
(string (format nil "a~Ab" char)) ;a non-standard string
(symbol (make-symbol string)) ;a non-standard symbol
(path #p"/etc/passwd") ;a non-standard pathname
(a1
(make-array ;a non-portable array
(make-list 9 :initial-element 1)))
(a2
(make-array 1025 :initial-element 0))) ;another non-portable array
(mapc 'quit
(list char string symbol path a1 a2))
(terpri)
(force-output))

Also, several of the Lisps that have a distinguished representation of
backquote syntax print backquote expressions using the backquote
character, even though no Lisp is required to parse those backquoted
expressions into lists similar to the printing implementations'
representation.

One implementation prints physical pathnames using sharp-s when
*PRINT-READABLY* is true. Printing a standard type using sharp-s is
non-portable, however, since other implementations don't necessarily
implement the same types as readable structure types. In fact some
other implementations can't read that sharp-s notation into a
pathname.

Note that a user can't portably affect character repertoires, physical
pathname syntax or values, and array size limits on an implementation,
so even if the user has control over the reading program, there's
nothing he can do if the printing program's implementation emitted
anything for such objects. This is different from structure types,
logical pathname hosts, and packages, where the user can at least
arrange things so that these will parse, at least so long as the
structure type names aren't also names of standard types.

Tim Bradshaw

unread,
Mar 11, 2007, 8:32:18 PM3/11/07
to
On 2007-03-11 23:07:15 +0000, Richard M Kreuter <kre...@progn.net> said:

> If we're discussing this as a matter along the lines of "what should
> the next standard look like", then probably specifying a variable that
> means what your *PRINT-PORTABLY* does would be useful, for the reasons
> described in the DATA-IO writeup. (Actually for maximal usefulness,
> such a variable should also prevent implementations from printing any
> instance of a standard type that lacks a standard read syntax while
> the variable is true.) Whether getting such a variable involves a
> clarification/restriction of the existing *PRINT-READABLY* or adding a
> new variable is a minor and essentially political point, IMO, so long
> as WITH-STANDARD-IO-SYNTAX binds whichever variable it is to true, and
> authors of PRINT-OBJECT are informed that their methods must not emit
> non-standard syntax while the variable is true.

This is really all I'm interested in - I'm profoundly uninterested in a
CL-like language which isn't upwardly compatible with CL.

>
> If we're discussing "what should a CL-like language, not necessarily
> CL as it is now, be like", then I'd say that while your
> *PRINT-PORTABLY* would be pretty handy for portability, your
> *PRINT-READABLY* doesn't need to be in such a language. Here's why:
> there are lots of ways to print Lisp objects parseably but
> non-portably, so what's the point of having exactly one variable that
> means "you may print non-standardly, so long as the output can be
> parsed under some unknown circumstances"? More to the point, why not
> leave it to people who want non-standard syntaxes to devise their own
> protocols to arrange for it, given that they can already do so in CL?

They could, but judging by the appalling botch people typically make of
it I'd much rather force something at least slightly well designed (not
necessarily *print-readably* etc) on them. I imagine the default thing
would be everyone having their own different special variable with
subtly differing and incompatible semantics. *print-readably* is
better than that, even as currently interpreted by most programs.

> As I said, this is academic. As things are, no implementation
> restricts itself to printing portably when *PRINT-READABLY* is true
> (sample below).

Even if the implementation were to so restrict itself for types it
knows, it can never force programs to do so.

I think one problem is that (I think - apologies if I am wrong) no one
who was involved in the standard in a major way reads cll any more, so
it is now hard to tell what the intended meaning of things was. If
it's not clear, I'm in favour of the `make a best attempt and don't
stress too much about the readtable' approach, which turns out to be
what most programs (which make any attempt at all) do now.

--tim

Edi Weitz

unread,
Mar 11, 2007, 8:59:30 PM3/11/07
to
On Mon, 12 Mar 2007 00:32:18 +0000, Tim Bradshaw <t...@tfeb.org> wrote:

> I think one problem is that (I think - apologies if I am wrong) no
> one who was involved in the standard in a major way reads cll any
> more, so it is now hard to tell what the intended meaning of things
> was.

At least Barry Margolin and Steven Haflich post here from time to
time.

--

Lisp is not dead, it just smells funny.

Real email: (replace (subseq "spam...@agharta.de" 5) "edi")

Pascal Bourguignon

unread,
Mar 12, 2007, 3:02:17 AM3/12/07
to
Tim Bradshaw <t...@tfeb.org> writes:

Well, the standard doesn't guaranty that you'll be able to print
readably your stuff, only that an error will be signaled if you try to
print something that cannot be printed readably, when *PRINT-READABLY*
is true. And to make this guaranty, the standard needs you to use
PRINT-UNREADABLE-OBJECT in your PRINT-OBJECT methods.

For the rest, if you want to serialize some data in a way you can read
it back and rebuild an equivalent object, you're on your own.

Tim Bradshaw

unread,
Mar 12, 2007, 2:26:51 PM3/12/07
to
On 2007-03-12 07:02:17 +0000, Pascal Bourguignon <p...@informatimago.com> said:

> And to make this guaranty, the standard needs you to use
> PRINT-UNREADABLE-OBJECT in your PRINT-OBJECT methods.

No, it doesn't. It requires your methods to behave appropriately with
respect to *PRINT-READABLY*, which behaviour it is up to you to ensure.

Pascal Bourguignon

unread,
Mar 13, 2007, 3:58:23 AM3/13/07
to
Tim Bradshaw <t...@tfeb.org> writes:

Yes, of course. The simpliest way being to use
print-unreadable-object, but you can do it yourself if you want to.

--
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org

Tim Bradshaw

unread,
Mar 13, 2007, 4:19:37 AM3/13/07
to
On 2007-03-13 07:58:23 +0000, Pascal Bourguignon <p...@informatimago.com> said:

> Yes, of course. The simpliest way being to use
> print-unreadable-object, but you can do it yourself if you want to.

What I meant was that if you want to print *readably* (assuming you
take the common liberal interpretation of *PRINT-READABLY* & ignore the
spec) then you have to do it yourself.

--tim

0 new messages