From: Tunc Simsek
Subject: [constants] from a reader macro
Date: 
Message-ID: <Pine.SOL.4.10.10002232042080.20547-100000@tudor.EECS.Berkeley.EDU>
Hi,

I'm having trouble with lisp constants.

Suppose I define a reader macro:

(defun foo (stream char)
    `(make-array 10000 :element-type 'double-float))

(set-macro-character ··@ #'foo)

In this silly example each time lisp sees a @ it will return
a big array.

The question is whether I can make it return the same array
each time it sees it:

(dotimes (i 10000)
  @)

should only create one array, i.e. in my opinion, a CONSTANT.

Thanks in advance,
Tunc

From: Samir Barjoud
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <wkzosrkrd8.fsf@mindspring.com>
Tunc Simsek <······@tudor.EECS.Berkeley.EDU> writes:

> Hi,
> 
> I'm having trouble with lisp constants.
> 
> Suppose I define a reader macro:
> 
> (defun foo (stream char)
>     `(make-array 10000 :element-type 'double-float))
> 
> (set-macro-character ··@ #'foo)
> 
> In this silly example each time lisp sees a @ it will return
> a big array.
> 
> The question is whether I can make it return the same array
> each time it sees it:
> 
> (dotimes (i 10000)
>   @)
> 
> should only create one array, i.e. in my opinion, a CONSTANT.
> 

Your reader macro function is returning a form that makes an array.
Instead, make it return an array by removing the backquote.

-- 
Samir Barjoud
·····@mindspring.com
From: Erik Naggum
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <3160367893782736@naggum.no>
* Tunc Simsek <······@tudor.EECS.Berkeley.EDU>
| Suppose I define a reader macro:
| 
| (defun foo (stream char)
|     `(make-array 10000 :element-type 'double-float))
| 
| (set-macro-character ··@ #'foo)

  I assume this is either a serious confusion or an instructive example
  whose purpose I don't understand, but to which you can apply answers.

| In this silly example each time lisp sees a @ it will return a big array.

  answering the confusion part: it is important to keep in mind exactly
  which part of "lisp" sees it under which conditions, and what it returns,
  not to forget to what it returns it.  the Lisp reader will see the @ and
  return the _list_ it received from foo.  if supplied at the top-level,
  this list is now a form the _evaluation_ of which returns an array, but
  the Lisp reader is by now long gone, having completed its job.  if read
  as part of some source code, it will only be folded into the source and
  later processed with that source code.

| The question is whether I can make it return the same array each time it
| sees it:
| 
| (dotimes (i 10000)
|   @)

  as indicated above, this is exactly identical to

(dotims (i 10000)
  (make-array 10000 :element-type 'double-float))

  and what happens from then on is not related to the Lisp reader at all,
  but to the normal behavior of the evaluator and compiler.

| should only create one array, i.e. in my opinion, a CONSTANT.

  however, if you remove the backquote in your misguided reader macro, foo
  will return a new array that will be treated as a constant by whatever
  called the Lisp reader each time, but again, the Lisp reader is long gone
  when this decision is made.

  it seems by your use of the backquote that your core confusion is to
  believe that "macro" in "reader macro" is the same kind of "macro" as in
  "macro function".  it isn't.  reader macros is a very powerful mechanism
  to change the syntax of the language, move certain operations into
  read-time (essentially pre-compile-time), and to abbreviate common forms.
  reader macros actually make up all the syntax of the language, such that
  the reader macro for #\( builds lists.

  I think the reader macro system is absolutely fantastic, but it takes a
  lot of skill to use it productively, and a lot of serious concern to see
  when not to use it, just as it takes a lot of intellectual effort to keep
  syntax simple and clean in general, much more than people generally think
  -- as witness C++ and Perl, but I'll avoid the digression.

#:Erik
From: Tunc Simsek
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <Pine.SOL.4.10.10002240034350.20636-100000@tudor.EECS.Berkeley.EDU>
I see your points.  The answer I was looking for was the removal of 
the "misguided" backquote.  Thanks.

Tunc 

I have a few remarks though.

On 24 Feb 2000, Erik Naggum wrote:

> * Tunc Simsek <······@tudor.EECS.Berkeley.EDU>
> | Suppose I define a reader macro:
> | 
> | (defun foo (stream char)
> |     `(make-array 10000 :element-type 'double-float))
> | 
> | (set-macro-character ··@ #'foo)
> 
>   I assume this is either a serious confusion or an instructive example
>   whose purpose I don't understand, but to which you can apply answers.

The real example defines a reader for #\[ to construct matrices, and was
way too long to put here.  That one returns something like `(make-matrix
which should now read (make-matrix ... (i.e. without the backquote.

> 
> | In this silly example each time lisp sees a @ it will return a big array.
> 
>   answering the confusion part: it is important to keep in mind exactly
>   which part of "lisp" sees it under which conditions, and what it returns,
>   not to forget to what it returns it.  the Lisp reader will see the @ and
>   return the _list_ it received from foo.  if supplied at the top-level,
>   this list is now a form the _evaluation_ of which returns an array, but
>   the Lisp reader is by now long gone, having completed its job.  if read
>   as part of some source code, it will only be folded into the source and
>   later processed with that source code.
> 
> | The question is whether I can make it return the same array each time it
> | sees it:
> | 
> | (dotimes (i 10000)
> |   @)
> 
>   as indicated above, this is exactly identical to
> 
> (dotims (i 10000)
>   (make-array 10000 :element-type 'double-float))
> 
>   and what happens from then on is not related to the Lisp reader at all,
>   but to the normal behavior of the evaluator and compiler.
> 
> | should only create one array, i.e. in my opinion, a CONSTANT.
> 
>   however, if you remove the backquote in your misguided reader macro, foo
>   will return a new array that will be treated as a constant by whatever
>   called the Lisp reader each time, but again, the Lisp reader is long gone
>   when this decision is made.
> 
>   it seems by your use of the backquote that your core confusion is to
>   believe that "macro" in "reader macro" is the same kind of "macro" as in
>   "macro function".  it isn't. 

I must confess that I don't understand this remark, they behave in the
same way, their ranges are lisp code.

>   reader macros is a very powerful mechanism
>   to change the syntax of the language, move certain operations into
>   read-time (essentially pre-compile-time), and to abbreviate common forms.
>   reader macros actually make up all the syntax of the language, such that
>   the reader macro for #\( builds lists.
> 
>   I think the reader macro system is absolutely fantastic, but it takes a
>   lot of skill to use it productively, and a lot of serious concern to see
>   when not to use it, just as it takes a lot of intellectual effort to keep
>   syntax simple and clean in general, much more than people generally think
>   -- as witness C++ and Perl, but I'll avoid the digression.

I agree that unnecessary complication should be avoided.  My intent is to
get a simple way of expressing constant matrices which I use a lot and
don't like to type in (make-matrix ... all the time.  I actually know of
one problem with using #\[ as a macro character: allegro uses it as
a super paranthesi.  

> 
> #:Erik
> 
> 
From: Erik Naggum
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <3160383123856271@naggum.no>
* Erik Naggum
| it seems by your use of the backquote that your core confusion is to
| believe that "macro" in "reader macro" is the same kind of "macro" as in
| "macro function".  it isn't.

* Tunc Simsek
| I must confess that I don't understand this remark, they behave in the
| same way, their ranges are lisp code.

  no.  that's the issue.  the "range" of macros is Lisp code which will be
  processed by the caller, usually the compiler on code it processes.  the
  "range" of reader macros is Lisp objects the Lisp reader was asked to
  pick up from some textual input source, such as by the compiler when it
  compiles files.  viz, a macro to build a matrix would return the code to
  be evaluated or compiled instead of the macro form, while a reader macro
  to build a matrix would return the matrix as a constant object.

  moreover, they do not behave in the same way.  a macro function is called
  with Lisp code it can transform at will, while a reader macro is expected
  to build Lisp objects from parsing input.  the "domain" of the former is
  Lisp objects and code, while the "domain" of the latter is characters and
  streams.  this must be understood in depth before you can make use of
  reader macros productively.  most Lisp programmers don't know how the
  Lisp reader and printer work to begin with, or how to add new objects to
  the read-write-consistency paradigm.  indeed, not understanding how Lisp
  has solved this very difficult problem is why most designers of protocols
  and syntaxes get them so incredibly wrong.

| My intent is to get a simple way of expressing constant matrices which I
| use a lot and don't like to type in (make-matrix ... all the time.

  this is good.  however, you should regard your reader macro as a
  short-cut for #.(make-matrix ...), not for (make-matrix ...) if you want
  to build the matrix in the reader macro (and nothing else makes sense).

| I actually know of one problem with using #\[ as a macro character:
| allegro uses it as a super paranthesi.

  which "allegro" is that?  Allegro CL does not violate the standard by
  interpreting [ and ] as anything but ordinary symbol name constituents.

#:Erik
From: Tunc Simsek
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <Pine.SOL.4.10.10002240723290.21414-100000@tudor.EECS.Berkeley.EDU>
On 24 Feb 2000, Erik Naggum wrote:

> * Erik Naggum
> | I actually know of one problem with using #\[ as a macro character:
> | allegro uses it as a super paranthesi.
> 
>   which "allegro" is that?  Allegro CL does not violate the standard by
>   interpreting [ and ] as anything but ordinary symbol name constituents.

Here is an excerpt from my Allegro CL 3.0.1 (win) on-line doc:
[

Terminating macro character
Allegro CL for Windows extension 
Description: acts as an opening super parenthesis. See ] .


]

Terminating macro character
Allegro CL for Windows extension 
Description: acts as a closing super parenthesis. It is equivalent to
reading any number of closing parentheses, closing back to the last [ , or
to the top level if no unclosed [  has been read.

 > 
> #:Erik
> 
> 

Tunc
From: Tim Bradshaw
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <ey3ln4a7eg1.fsf@cley.com>
* Tunc Simsek wrote:
> Here is an excerpt from my Allegro CL 3.0.1 (win) on-line doc:

Remember that that's a completely different implementation than the
current ACL for windows (5.0.1).

--tim
From: Erik Naggum
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <3160397620998575@naggum.no>
* Tunc Simsek <······@tudor.EECS.Berkeley.EDU>
| Here is an excerpt from my Allegro CL 3.0.1 (win) on-line doc:

  geez, that's _ancient_.

#:Erik
From: Erann Gat
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <gat-2402001038200001@milo.jpl.nasa.gov>
In article <··············@rainbow.studorg.tuwien.ac.at>,
········@ag.or.at wrote:

> What do you (and of course others) think about the following piece of
> code?  Comments appreciated.

A little top-level comment describing what this code is intended to do
would be helpful.

CHANGE-CLASS is one of those things like EVAL that ought to raise a
red flag whenever you see it.  In this case you can simplify things
a lot by doing:

(defun file-reader (stream subchar arg)
  "This function is to be used in a SET-DISPATCH-MACRO-CHARACTER definition."
  (declare (ignore subchar arg))
  `(make-instance (or (assoc (pathname-type (path file))
                             *type-file-alist* :test #'string=)
                      'file)
                 :path ,(read stream t nil t)))

and get rid of maybe-change-class.

You can also make you file type check case-insensitive (if that's what
you want) by using string-equal instead of string=.

Erann Gat
···@jpl.nasa.gov

> ======================================================================
> (defclass file ()
>   ((path :accessor path :initarg :path :initform nil)))
> 
> (defclass ipd-file (file) ())
> (defclass pbf-file (file) ())
> (defclass pif-file (file) ())
> 
> (defparameter *type-file-alist*
>     '(("ipd" . ipd-file)
>       ("pbf" . pbf-file)
>       ("pif" . pif-file)))
> 
> #|
> (defmethod print-object ((f file) stream)
>   (print-unreadable-object (f stream :type t :identity nil)
>     (format stream "~S" (path f)))
>   f)
> |#
> 
> (defmethod print-object ((file file) stream)
>   (format stream "#f\"~A\"" (translate-logical-pathname (path file))))
> 
> (defmethod initialize-instance :after ((file file) &rest init-args)
>   (declare (ignore init-args))
>   ;; ensure (path file) is a pathname
>   (with-slots (path) file
>     (when (and path (not (pathnamep path)))
>       (setf path (pathname path))))
>   (maybe-change-class file))
> 
> (defmethod maybe-change-class ((file file))
>   "If the type of the path of FILE is known in *TYPE-FILE-ALIST*, change
its class accordingly."
>   (flet ((associate ()
>            (assoc (pathname-type (path file)) *type-file-alist* :test
#'string=)))
>     (if (and (pathnamep (path file))
>              (stringp (pathname-type (path file)))
>              (associate))
>         (change-class file (cdr (associate)))
>       file)))
> 
> (defun file-reader (stream subchar arg)
>   "This function is to be used in a SET-DISPATCH-MACRO-CHARACTER definition."
>   (declare (ignore subchar arg))
>   `(make-instance 'file :path ,(read stream t nil t)))
> 
> (set-dispatch-macro-character #\# #\f 'file-reader)
> ======================================================================
From: Raymond Toy
Subject: change-class? Re: [constants] from a reader macro
Date: 
Message-ID: <4nd7pm1id0.fsf_-_@rtp.ericsson.se>
>>>>> "Erann" == Erann Gat <···@jpl.nasa.gov> writes:

    Erann> CHANGE-CLASS is one of those things like EVAL that ought to raise a
    Erann> red flag whenever you see it.  In this case you can simplify things

Why is that?

A while ago I had written an interference simulation system for
cellular.  It had mobile phone users that were outdoors and indoors,
so the interference seen by these two types of users were modelled
differently.  Although I didn't implement this part, the users were
allowed to move around.  If the indoor user moved too far from its
home, it became an outdoor user.  I was going to implement this via
change-class.

I could have done this in other ways too like having a slot indicating
if the user was indoor or outdoors, but changing the class seemed just
as effective.

Is this a bad use of change-class?

Ray
From: Robert Monfera
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <38B5ACAE.4A199A05@fisec.com>
Erann Gat wrote:

> CHANGE-CLASS is one of those things like EVAL that ought to raise a
> red flag whenever you see it.

I disagree, and am interested in the justification logic from you, or
stories when a solution turned out to be outright flawed because of
CHANGE-CLASS.  Here's my current thinking:

CHANGE-CLASS is a first-class citizen of OOP and CLOS, related to object
identity, inheritance and polymorphism.  (It also comes handy for
prototype-based systems.)  CHANGE-CLASS recognizes the fact that objects
(real or contrived) may substantially and qualitatively change over
time, while preserving their identity.

A simple example is a business partner class:  business partner
relationship (which you'd want to depict in an object) has many facets.
A business partner may assume the role of a customer, vendor, investor,
creditor etc., in addition to their roles in the initial engagement with
our firm.  A business partner may become the subsidiary of another firm
through acquisition, become unworthy of credit, become a competitor,
with obvious accompanying behavioral changes.

All these types of common changes are ideally reflected with
CHANGE-CLASS and I don't know of a way of doing it more elegantly.  The
need comes up in many (most?) non-trivial OO-modeling problems in the
business world.

Another example, which has also something to do with GUI (for those who
mistakenly think OO is primarily useful for GUI purposes) is the
functionality of TurboTax or similar "wizard"-like programs.  If you
indicate at the beginning of the form that you're married and you want
to file a joint return, it will have effects several screens later
(e.g., in the form of asking your spouse's name and income).  You may
fill your return completely, including these parts.  You may then change
your mind about the joint return, rightfully expecting the program to
change screens accordingly, while retaining data still relevant for the
tax calculation (and maybe still remembering your spouse's data in the
background in case you revert).

>  In this case you can simplify things
> a lot by doing:
>
> (defun file-reader (stream subchar arg)
    [...]
>   (declare (ignore subchar arg))
>   `(make-instance (or (assoc (pathname-type (path file))
>                              *type-file-alist* :test #'string=)
>                       'file)
>                  :path ,(read stream t nil t)))

Yes, this is much simpler and shorter.  He could also use a generic
function to issue MAKE-INSTANCE, having an uspecialized method and
symbol-specialized methods for PIF, PBF and IPD the benefit is that it
would yield an easily extendable framework (which may or may not be
Clemens' goal).

The class of an object in an application may not only change because the
real-world object (if any) changed, but because we acquired new
knowledge about it.

For this reason, even with streams, the use of CHANGE-CLASS is
potentially a good idea, for example, the analysis of the first few
hundred bytes would determine the type (class) of the file, like whether
it is fixed-width or delimited, or if there is a header line.  Even for
the low-level analysis it may be desirable to exploit the behavior of
the default class.  In this case Clemens could still call a GF from
within INITIALIZE-INSTANCE to perform the "class upgrade", which would
do (symbol) dispatch instead of a manual implementation of dispatch with
an alist.

Incidentally CL-HTTP uses CHANGE-CLASS in a somewhat similar manner to
Clemens' example when exporting URLs, although I didn't analyze it to
the extent that I can judge its appropriateness.

I have to admit though that CHANGE-CLASS can be misused, such as most
other functions.  In the present case, if that's all Clemens wanted,
your solution gives the denser code (not implying that CHANGE-CLASS is
inappropriate).

Best regards
Robert
From: Pierre R. Mai
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <87d7pl31mi.fsf@orion.dent.isdn.cs.tu-berlin.de>
Clemens Heitzinger <········@rainbow.studorg.tuwien.ac.at> writes:

> One advantage of my setup is that known file types are automatically
> used, ie, I can say (make-instance 'file :path "foo.pif") and get a
> PIF-FILE object.  (Well, if somebody thinks this is a bad idea, please
> say so.)

So. ;)

IMHO you shouldn't overload make-instance to do this automagic
change-class.  When a user says (make-instance 'a), he should be able
to expect to get an object whose class is a, and not some other (sub-) 
class, regardless of the specific a in question.

I wouldn't object to something like

(make-file :path "foo.pif")

or even

(make-file-instance 'file :path "foo.pif")

or whatever.  But overloading make-instance to do this is not very
clear, IMHO.

> This fits my situation.  I suppose changing the class of an object in
> INITIALIZE-INSTANCE is ok.

I'd disagree, see above.

Note that I'm not objecting to change-class, just to doing the
change-class in initialize-instance.

Regs, Pierre.

-- 
Pierre Mai <····@acm.org>         PGP and GPG keys at your nearest Keyserver
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]
From: Chris Double
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <wkn1oosmcr.fsf@double.co.nz>
····@acm.org (Pierre R. Mai) writes:

> IMHO you shouldn't overload make-instance to do this automagic
> change-class.  When a user says (make-instance 'a), he should be
> able to expect to get an object whose class is a, and not some other
> (sub-) class, regardless of the specific a in question.

Why is that? 

In Dylan it seems quite common to use make(<some-class>) and have make
return either <some-class> or a subclass. In the DUIM windowing
framework for example, you do a make(<push-button>) but you actually
get an instance of a subclass like <win32-push-button>. make(...) in
Dylan is the equivalent of make-instance in LISP.

I thought this would be a similar idiom in LISP (given Dylan's LISP
heritage) but from the replies in this thread I guess not.

Chris.
From: Robert Monfera
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <38B75367.AD3F113@fisec.com>
I think the idiom makes sense, but I'm divided over the details.

On one hand, Pierre and Tim have a valid point: if MAKE-INSTANCE is to
return an instance of the specified class (and doing anything else is a
violation of the letter, but probably not the intent of ANSI CL spec),
then readers of the code may be puzzled.  I don't know about safety
measures in Dylan, but CHANGE-CLASS in CL may change the class of the
newborn object to anything.  (Technically speaking, implementations
should have no problems with doing whatever the user wants in an :AFTER
method of INITIALIZE-INSTANCE).

On the other hand, I don't like the idea of necessarily creating helper
functions like CREATE-FILE et al if this consideration is the _only_
reason to do so, as they unnecessarily increase the number of exported
functions.  I also don't expect that any benefit arises from strictly
observing the letter of the spec, by other words, no reasonable
implementation or user code should depend on the class of the new
instance.

To bridge the gap in an inexpensive way, one could invent one single
generic function to piggyback on MAKE-INSTANCE while avoiding its
overloading.  How about MAKE?

Robert

> I thought this would be a similar idiom in LISP (given Dylan's LISP
> heritage) but from the replies in this thread I guess not.
>
> Chris.
From: Pierre R. Mai
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <87900813tg.fsf@orion.dent.isdn.cs.tu-berlin.de>
Chris Double <·····@double.co.nz> writes:

> ····@acm.org (Pierre R. Mai) writes:
> 
> > IMHO you shouldn't overload make-instance to do this automagic
> > change-class.  When a user says (make-instance 'a), he should be
> > able to expect to get an object whose class is a, and not some other
> > (sub-) class, regardless of the specific a in question.
> 
> Why is that? 

Mostly because there is no precedent in ANSI CL (or most libraries and 
systems I've seen) for this sort of behaviour, so it would run counter 
to the expectations of an informed user, which would be confusing and
lead to serious maintenance hazards, IMHO.

Note that I'm not saying that the way ANSI CL handles this is the only 
true and right way.  Since Dylan is another language, with another
specification and different precedents, overloading make to
automagically return some subclass is something that informed users of 
Dylan can expect.

Regs, Pierre.

-- 
Pierre Mai <····@acm.org>         PGP and GPG keys at your nearest Keyserver
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]
From: Tim Bradshaw
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <ey3n1ops8ah.fsf@cley.com>
* Clemens Heitzinger wrote:
> One advantage of my setup is that known file types are automatically
> used, ie, I can say (make-instance 'file :path "foo.pif") and get a
> PIF-FILE object.  (Well, if somebody thinks this is a bad idea, please
> say so.)

Although I'm not against CHANGE-CLASS (apart from the fact that on
some (non-current, as far as I know) implementations it's *extremely*
inefficient as it basically seems to cause all the effective method
caches to get flushed!), I think this is a really bad example.

If I say (make-instance 'x), I expect to get precisely an X, not some
other class.

I think that it's quite reasonable to have a `make appropriate class'
type function, but you'd want to avoid using MAKE-INSTANCE to do that.
I kind of think that you'd also want to avoid doing a CHANGE-CLASS in
this case, but that's really an implementation issue.

In some code I recently wrote I have things called UPTs
(urlpath-trees) which have several internal representations with
various tradeoffs, and the make-a-new-empty-tree function lets you say

	(make-upt :type x)

where X is some kind of hint as to the representation you want (I
think you can say :LISTY, :HASHY, or :SMART).  (:TYPE is an
unfortunate keyword name in this context, I know).

The :SMART ones actually use CHANGE-CLASS from listy to hashy if the
directories get big enough, which is a really nice use of CHANGE-CLASS
I think as it optimises lookup performance dynamically while keeping
the tree overhead small (small directories stay listy), and requiring
only one simple method on UPDATE-INSTANCE-FOR-REDEFINED-CLASS to do
all the work (and an :AROUND method on the add-child GF to trigger it
actually).

I measured it on some biggish trees and the change-class one is just
as efficient to build the tree, and more efficient for general lookup.
As far as I can see the alternative implementation would require some
kind of proxy class for the smart nodes which forwarded all methods to
the real object, and was willing to build a new real object from the
old one if need be.  I had one that did that (because I felt it would
be more conventional for students to see) but it was just masses of
extra code, which you had to fix for no very good reason every time
the protocol for the non-proxy things changed.  I guess there's a
design pattern for things like that, it sounds sufficiently like a
losing solution that there would need to be (`yes, it's OK to do this
dreadful crap, because there's a *pattern*'!)

(I'd include the code here but it's for a student exercise so I can't
quite yet...)

--tim
From: Erann Gat
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <gat-2402001031060001@milo.jpl.nasa.gov>
In article
<·········································@tudor.EECS.Berkeley.EDU>, Tunc
Simsek <······@tudor.EECS.Berkeley.EDU> wrote:

> I agree that unnecessary complication should be avoided.  My intent is to
> get a simple way of expressing constant matrices which I use a lot and
> don't like to type in (make-matrix ... all the time.

Why not just:

(defconstant @ (make-matrix ...))

(Editorial comment: you should probably choose a different name than @,
constant-matrix-1 perhaps.)

Erann Gat
···@jpl.nasa.gov
From: Michael Kappert
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <38B4FDF5.EC92F487@iitb.fhg.de>
Erik Naggum wrote:
 
> * Tunc Simsek <······@tudor.EECS.Berkeley.EDU>
> | Suppose I define a reader macro:
> |
> | (defun foo (stream char)
> |     `(make-array 10000 :element-type 'double-float))
> |
> | (set-macro-character ··@ #'foo)

> | The question is whether I can make it return the same array each time it
> | sees it:
> |
> | (dotimes (i 10000)
> |   @)

In this example, the reader sees @ only once.

> | should only create one array, i.e. in my opinion, a CONSTANT.
 
>   [...] if you remove the backquote in your misguided reader macro, foo
>   will return a new array that will be treated as a constant by whatever
>   called the Lisp reader each time, but again, the Lisp reader is long gone
>   when this decision is made.

If you want the reader to return the same array every time it sees a @,
shouldn't FOO be defined something like

(let ((my-array ()))
  (defun foo (stream char)
    (or my-array (setf my-array (make-array ... )))))

Or did i misunderstand the original poster? It seems, a reader macro isn't
the best way to do this, DEFCONSTANT may be more appropriate.


Michael 


-- 
Michael Kappert
Fraunhofer IITB
Fraunhoferstr. 1                                       Phone: +49(0)721/6091-477
D-76131 Karlsruhe, Germany                             EMail: ···@iitb.fhg.de
From: Erik Naggum
Subject: Re: [constants] from a reader macro
Date: 
Message-ID: <3160379902079136@naggum.no>
* Michael Kappert <···@iitb.fhg.de>
| If you want the reader to return the same array every time it sees a @,
| shouldn't FOO be defined something like
| 
| (let ((my-array ()))
|   (defun foo (stream char)
|     (or my-array (setf my-array (make-array ... )))))

  presuming that it will be called at least once, you could initialize the
  binding with the value, or use what I prefer these days, load-time-value.

#:Erik