From: ·······@genworks.com
Subject: writing out expressions prepended by #.
Date: 
Message-ID: <3AE9EEC3.13F4B3ED@genworks.com>
Sorry if i'm missing something obvious, but:...

What is the proper way to write out expressions which
are prepended with "#.", so they will be evaluated
upon being read?

For example, I have a list of "point" objects, which 
have to be created with the function (macro, actually)
"make-point" (that is, their printed representation is
not sufficient to read them back in, so one has to 
re-create them by evaluating an expression). So I want
to write this list out as a list of expressions, similar
to this:

 (#.(make-point 1 2 3)
  #.(make-point 4 5 6)
  ...)

such that when read in, each expression will automatically
be converted into the result of the call to make-point.

I can make a list of the make-point expressions with
something like the following:

(mapcar #'point-expression point-list)

which will produce 

   ((make-point 1 2 3)
    (make-point 4 5 6)
    ...)

But, how do I produce a list in which each element ends
up prepended by the "#." in the printed representation?

(I know i could kludge something together with strings
containing the "#.", but I am hoping to be able to 
pretty-print an actual list)

Thanks!

 -dave

From: Barry Margolin
Subject: Re: writing out expressions prepended by #.
Date: 
Message-ID: <IzmG6.87$EE6.2062@burlma1-snr2>
In article <·················@genworks.com>,  <·······@genworks.com> wrote:
>
>Sorry if i'm missing something obvious, but:...
>
>What is the proper way to write out expressions which
>are prepended with "#.", so they will be evaluated
>upon being read?
>
>For example, I have a list of "point" objects, which 
>have to be created with the function (macro, actually)
>"make-point" (that is, their printed representation is
>not sufficient to read them back in, so one has to 
>re-create them by evaluating an expression). So I want
>to write this list out as a list of expressions, similar
>to this:
>
> (#.(make-point 1 2 3)
>  #.(make-point 4 5 6)
>  ...)
>
>such that when read in, each expression will automatically
>be converted into the result of the call to make-point.
>
>I can make a list of the make-point expressions with
>something like the following:
>
>(mapcar #'point-expression point-list)
>
>which will produce 
>
>   ((make-point 1 2 3)
>    (make-point 4 5 6)
>    ...)
>
>But, how do I produce a list in which each element ends
>up prepended by the "#." in the printed representation?
>
>(I know i could kludge something together with strings
>containing the "#.", but I am hoping to be able to 
>pretty-print an actual list)

There's nothing that automatically prints objects using #. syntax.  If
you've defined the POINT type using DEFCLASS or DEFSTRUCT, you can arrange
for a user-defined function to be used to print them:

(defmethod print-object (self stream)
  (format stream (if (or *print-readably* *print-escape*)
                     "#.(make-point ~S ~S ~S)"
                     "#.(make-point ~A ~A ~A)")
          (point-x self) (point-y self) (point-z self)))

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Kent M Pitman
Subject: Re: writing out expressions prepended by #.
Date: 
Message-ID: <sfw4rv99af9.fsf@world.std.com>
Barry Margolin <······@genuity.net> writes:

> There's nothing that automatically prints objects using #. syntax.  If
> you've defined the POINT type using DEFCLASS or DEFSTRUCT, you can arrange
> for a user-defined function to be used to print them:
> 
> (defmethod print-object (self stream)
>   (format stream (if (or *print-readably* *print-escape*)
>                      "#.(make-point ~S ~S ~S)"
>                      "#.(make-point ~A ~A ~A)")
>           (point-x self) (point-y self) (point-z self)))

Careful to specify the class, as in:

(defmethod print-object ((self point) stream)
  ...)


Doing it without the class defaults to class T, which is something users
shouldn't be redefining.

I assume this was just a typo on Barry's part, but wanted to make sure 
anyone experimenting does this right.

- - - - -

Of course, the other way to do this is to define the point with defstruct
and then it will be re-readable with #S with no special work.

The only disadvantage of #.(...) is that a lot of people bind
*read-eval* when reading forms, and in that case you'll lose on the
re-read.  To counteract that, you might be better off to take some
other dispatch on # and make something similar to #S but with
user-definable characteristics.  e.g., define a #_ or #U or some other
undefined thing to read a (POINT :X 3 :Y 4 :Z 5) and turn it into
(apply #'make-instance the-expression-seen-by-read) to obtain the
object to return.  It's a darned shame that #S is not thusly defined.
I seem to recall I tried to get the committee to generalize its effect
but for some reason it didn't go through--maybe it was after the feature
freeze...
From: Erik Naggum
Subject: Re: writing out expressions prepended by #.
Date: 
Message-ID: <3197414092128104@naggum.net>
* Kent M Pitman
> The only disadvantage of #.(...) is that a lot of people bind *read-eval*
> when reading forms, and in that case you'll lose on the re-read.  To
> counteract that, you might be better off to take some other dispatch on #
> and make something similar to #S but with user-definable characteristics.
:
> I seem to recall I tried to get the committee to generalize its effect
> but for some reason it didn't go through--maybe it was after the feature
> freeze...

  I have taken to define #/ as a reader-macro akin to the format control,
  to read _registered_ types with associated functions, as I ran out of
  convenient ways to specify classes and such.

  In this particular case, #/point/(1 2 3), would require a registered type
  named point with an associated reader function that that would read as
  many arguments as it needs using whatever printer controls and reader
  functions it pleased, but it would of course be the question of more or
  less reasoanble usages, as with every other powerful mechanism.  E.g.,
  #/ip/192.168.150.155/26 could mean the address and a 26-bit mask for
  routing or matching purposes, whild #/ip/192.168.150.155:5555 could mean
  an address and a port number.  And #/md5/0123456789abcdeffedcba9876543210
  could mean the hexadecimal representation of an MD5 sum.

  Given this framework, would be a very simple task to supply macros that
  defined and registered reader functions and corresponding print-object
  methods for new classes.

#:Erik
-- 
  I found no peace in solitude.
  I found no chaos in catastrophe.
			-- :wumpscut:
From: Kent M Pitman
Subject: Re: writing out expressions prepended by #.
Date: 
Message-ID: <sfwelud17yn.fsf@world.std.com>
Erik Naggum <····@naggum.net> writes:

> * Kent M Pitman
> > The only disadvantage of #.(...) is that a lot of people bind *read-eval*
> > when reading forms, and in that case you'll lose on the re-read.  To
> > counteract that, you might be better off to take some other dispatch on #
> > and make something similar to #S but with user-definable characteristics.
> :
> > I seem to recall I tried to get the committee to generalize its effect
> > but for some reason it didn't go through--maybe it was after the feature
> > freeze...
> 
>   I have taken to define #/ as a reader-macro akin to the format control,
>   to read _registered_ types with associated functions, as I ran out of
>   convenient ways to specify classes and such.
> 
>   In this particular case, #/point/(1 2 3), would require a registered type
>   named point with an associated reader function that that would read as
>   many arguments as it needs using whatever printer controls and reader
>   functions it pleased, but it would of course be the question of more or
>   less reasoanble usages, as with every other powerful mechanism.  E.g.,
>   #/ip/192.168.150.155/26 could mean the address and a 26-bit mask for
>   routing or matching purposes, whild #/ip/192.168.150.155:5555 could mean
>   an address and a port number.  And #/md5/0123456789abcdeffedcba9876543210
>   could mean the hexadecimal representation of an MD5 sum.

The only problem with this is that there is a convention (not sure if it's
documented or not) that #<char> should be followed by exactly one readable
token, for the case of making #- skip the right number of tokesn in a place
where the object is not implemented.

>   Given this framework, would be a very simple task to supply macros that
>   defined and registered reader functions and corresponding print-object
>   methods for new classes.

I agree with your intent, and another notation I've periodically wished for
is like this: #_point(1 2 3)

But because of other practicalities would rather
#S(MD5 :CODE "0123456789abcdeffedcba9876543210")
and #S(IP :ADDRESS "192.168.150.155" :PORT "5555").
Absent support for extensible #S, #_ or whatever.
The other advantage of the #S approach is that if the parser is proprietary
for things like an IP address or a URL, it's easier to conjure a "parser" for
#S-style structures (since it's just an application of GETF) than for the
other notations you suggest, even if they are more compact.
From: Erik Naggum
Subject: Re: writing out expressions prepended by #.
Date: 
Message-ID: <3197580855623450@naggum.net>
* Kent M Pitman
> The only problem with this is that there is a convention (not sure if
> it's documented or not) that #<char> should be followed by exactly one
> readable token, for the case of making #- skip the right number of tokesn
> in a place where the object is not implemented.

  I do not agree with this.  Input to the reader that use these notations
  either have an in-syntax form at the top to establish the readtable, and
  that would fail before #- would fail, or operate under an assumption made
  explicit elsewhere if not in the input stream that such readtables are
  employed.

> The other advantage of the #S approach is that if the parser is
> proprietary for things like an IP address or a URL, it's easier to
> conjure a "parser" for #S-style structures (since it's just an
> application of GETF) than for the other notations you suggest, even if
> they are more compact.

  Compactness is not the driving concern.  The driving concern is the
  ability to register types (or whatever else is suitable) so that the
  syntax is _not_ open-ended as far as the reading process is concerned,
  such as #. is.  #. also returns objects of type t, whatever is returned
  as the primary value of the form evaluated, which may be a strain on the
  human reader of the code.  #/.../ would return objects of a known type,
  identified by name.  #S has this feature, but it requires a parsed-out
  list of arguments.  There are good reasons we invent new syntaxes, such
  as for pathnames, symbols-with-packages, etc, even though they have some
  costs: e.g., #S(symbol :name "FOO" :package "BAR") is conceptually the
  same as bar:foo.

#:Erik
-- 
  I found no peace in solitude.
  I found no chaos in catastrophe.
			-- :wumpscut:
From: David Bakhash
Subject: Re: writing out expressions prepended by #.
Date: 
Message-ID: <m3u23arns2.fsf@alum.mit.edu>
>>>>> "kmp" == Kent M Pitman <Kent> writes:

 kmp> It's a darned shame that #S is not thusly defined.

never thought about that, but yeah, since it's not asking to much to
make an implementation allow make-instance to work with structs as
well (I know most commercial ones do), this is an obvious extension.

So here's a question I probably should have asked ages ago:

  What would it take to have this change occur in ANSI Common Lisp?
  i.e. when will Common Lisp change, if ever?

I wouldn't mind things like this changing, though I also do realize
that such a change would modify the behaviour of some of the code
that's out there.  But in a case like this, it seems worthwhile.

dave
From: Kent M Pitman
Subject: Re: writing out expressions prepended by #.
Date: 
Message-ID: <sfwd79x178h.fsf@world.std.com>
David Bakhash <·····@alum.mit.edu> writes:

> >>>>> "kmp" == Kent M Pitman <Kent> writes:
> 
>  kmp> It's a darned shame that #S is not thusly defined.
> 
> never thought about that, but yeah, since it's not asking to much to
> make an implementation allow make-instance to work with structs as
> well (I know most commercial ones do), this is an obvious extension.
> 
> So here's a question I probably should have asked ages ago:
> 
>   What would it take to have this change occur in ANSI Common Lisp?

A miracle.

>   i.e. when will Common Lisp change, if ever?

Hopefully never.  The cost of it changing is very high.

> I wouldn't mind things like this changing, though I also do realize
> that such a change would modify the behaviour of some of the code
> that's out there.  But in a case like this, it seems worthwhile.

I think the change could be made enough compatibly that individual vendors
might be convinced to make this change as an extension, and we might be
able to have it be a de facto standard.

Send a bug report to your vendors.  Let's see if we can rally enough
individual vendors to make the extension that it gets in.

I *think* this is what I would ask for.  Someone correct me if this doesn't
sound right:

  If the <NAME> in #S(<NAME> . <OPTIONS>) is not defined as a structure,
  the effect of (APPLY #'MAKE-INSTANCE '<NAME> '<OPTIONS>)
  is done.

Frankly, I've never understood why we didn't just make it so that

  (MAKE-INSTANCE '<structure-class-name> ...)

was a synonym for 

  (MAKE-<structure-class-name> ...)

[well, or vice versa]

Then it would be really obvious how to implement #S and the extension
would fall out naturally instead of requiring dealing with structures
and non-structures as special cases.

One reason I advocated this #S notation, btw, is that it can be used for
built-in-classes as well, especially when *PRINT-READABLY* is true and
the standard syntax isn't enough to allow proper re-reading of the
structure.  For example, hash tables, displaced arrays, etc.
It requires some detailing to make sure the names of the "slots"
of these objects, such as they are, are named.  e.g., to decide that
an array's contents is its :contents or :storage or whatever, and whether
the length is explicit or implicit, and whether the contents beyond the
fill pointer is shown, and all that.  But still, these are things that
could have been worked out, and would have been useful to the community.

 #S(VECTOR :CONTENTS (1 2) :LENGTH 5 :FILL-POINTER 2 :ADJUSTABLE T)
vs
 #S(VECTOR :CONTENTS (1 2 3 4 5) :LENGTH 5 :FILL-POINTER 2 :ADJUSTABLE T)

or

 (SETQ X #1=#(1 2 3 4 5 6)
       Y #S(ARRAY :DISPLACED-TO #1# :DISPLACED-INDEX-OFFSET 2
                  :DIMENSIONS (2 2)))
From: Tim Moore
Subject: Re: writing out expressions prepended by #.
Date: 
Message-ID: <9cctkd$gd8$0@216.39.145.192>
It sounds like you're looking for some magic value that gets printed out
as "#.".  There's no portable way to do that, though some implementations
might have some magic that enables that.  To do what you want I'd try
this:

(defmethod print-object ((object point) stream)
  (if *print-readably*
      (format stream "#.(make-point ~S ~S ~S)"
	      (x object) (y object) (z object))
      (print-unreadable-object (object stream :type t :identity t))))

If I were going to go nuts with pretty printing I'd do this:

(defmethod print-object ((object point) stream)
  (if *print-readably*
      (format stream "#.~:<···········@_ ~S~_~S~_~S~:>"
	      (x object) (y object) (z object))
      (print-unreadable-object (object stream :type t :identity t))))

Of course, if I were going to do this I'd test any code I read on Usenet,
assuming the author hadn't :)

Tim

> 
> Sorry if i'm missing something obvious, but:...
> 
> What is the proper way to write out expressions which
> are prepended with "#.", so they will be evaluated
> upon being read?
> 
> For example, I have a list of "point" objects, which 
> have to be created with the function (macro, actually)
> "make-point" (that is, their printed representation is
> not sufficient to read them back in, so one has to 
> re-create them by evaluating an expression). So I want
> to write this list out as a list of expressions, similar
> to this:
> 
>  (#.(make-point 1 2 3)
>   #.(make-point 4 5 6)
>   ...)
> 
> such that when read in, each expression will automatically
> be converted into the result of the call to make-point.
> 
> I can make a list of the make-point expressions with
> something like the following:
> 
> (mapcar #'point-expression point-list)
> 
> which will produce 
> 
>    ((make-point 1 2 3)
>     (make-point 4 5 6)
>     ...)
> 
> But, how do I produce a list in which each element ends
> up prepended by the "#." in the printed representation?
> 
> (I know i could kludge something together with strings
> containing the "#.", but I am hoping to be able to 
> pretty-print an actual list)
> 
> Thanks!
> 
>  -dave
> 
> 
>