Subject: Re: I don't understand Lisp
From: rpw3@rigden.engr.sgi.com (Rob Warnock)
Date: 1998/09/13
Newsgroups: comp.lang.lisp
Message-ID: <6tgji9$26hk7@fido.engr.sgi.com>
Erik Naggum  <clerik@naggum.no> wrote:
+---------------
|   I take this to mean that you think the lexical analysis of Scheme and
|   Common Lisp are similar or the same.  this is not so.  Common Lisp has a
|   programmable reader that is used to read Lisp forms, while Scheme uses a
|   very static syntax that is even outside of Scheme itself.  (i.e., Common
|   Lisp uses READ and uses the value of *READTABLE* even for code, while
|   Scheme cannot use READ because the syntax is specified as sequences of
|   characters, not as forms.)
+---------------

Erik, I assume you're wearing some sort of "standards purist" hat while
saying this...?  ;-}  Yes, of course, in principle you are absolutely
correct, but in practice I don't know of a single Scheme implementation
that does *NOT* use the same lexer for the user-visible READ procedure and
the reader buried in the LOAD procedure and the top-level REPL. In fact,
now that EVAL is in R5RS, one could even make Scheme's LOAD an optional
procedure, which could be coded by the user as:

	(define (load fname)
	  (with-input-from-file fname
	    (lambda ()
	      (do ((exp (read) (read)))
		  ((eof-object? exp))		; note: returns unspec. value
		(eval exp (interaction-environment))))))

And, except for the lack of error-handling, this:

	(let loop ()
	  (display "my-repl> ")
	  (write (eval (read) (interaction-environment)))
	  (newline)
	  (loop))

is a perfectly functional REPL in every Scheme I've ever used. [O.k.,
so you have to leave off the 2nd arg to "eval" in the older ones...]

In fact, I can't see any way to *avoid* this, since R5RS explictly says
that READ "...is a parser for the nonterminal <datum>" [6.6.2], and
also, "Note that any string that parses as an <expression> also parses
as a <datum>." [7.1.2]  So it should be perfectly correct to use READ
for Scheme expressions (well-formed ones, that is).

On the other hand... There is no defined way in Scheme to extend or modify
the syntax accepted by READ. With only one or two ad-hoc exceptions (dare I
say "hacks"?), I haven't seen anything in the Scheme world that comes close
to the Common Lisp notion of *READTABLE*, and certainly nothing that works
the same way in more than one implementation. And that's quite unfortunate,
given the wide differences in lexical "extensions" supported by various
Schemes. Some allow |CaseSensitiveSymbols With Spaces InVerticalBars| and
some don't. Some allow #|multi-line comments|# and some don't. A very few
support "#."; most don't. Were there a widely-accepted readtable-equivalent,
one could gloss over these differences. But as it is, if one is trying to
write Scheme code which will be even barely portable, one must simply avoid
*everything* that's not explcitly mentioned in R5RS [or even R4RS]. (*sigh*)

Hmmmm... But on the third hand [as Niven & Pournelle say], in R5RS "READ"
is listed as a "library" procedure, which means that while conforming
implementations must provide one [it's not an "optional" library procedure]
it need not be primitive -- it can be implemented in terms of other, more
primitive features. Just start with "READ-CHAR", and parse it yourself.
(I've done that before, actually, as an exercise.) There are enough required
type-conversion routines [I'm thinking specifically of "string->symbol"
and "char->integer"] to allow building any Scheme object up out of pieces.
Maybe *that's* supposed to be "the Scheme way" to get reader extensibility...?


-Rob

-----
Rob Warnock, 8L-855		rpw3@sgi.com
Applied Networking		http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673
2011 N. Shoreline Blvd.		FAX: 650-964-0811
Mountain View, CA  94043	PP-ASEL-IA