[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Issue: READ-CASE-SENSITIVITY (Version 1)

> I appreciate your good intentions in writing this proposal, [...]

It's sometimes difficult to reply to a long message, for the reply may
be long as well, an no-one really wants to read a bunch of long
messages.  So I will try to keep this as short as possible.

First, I think we should separate some issues:

  0. Lower-case vs. upper-case.
  1. Case-sensitivity in code (as a style or convention).
  2. Case-sensitivity as an option when reading.
  3. The addition of a new parameter vs. an operation on readtables.
  4. The particular choice of *READ-CASE*, :UPCASE, and :DOWNCASE.

I, personally, do not want to argue about whether (1) is a good idea.
It's the sort of thing about which people can endlessly disagree.  The
same goes for (0).  I don't have any particular attachment to (5) and
am willing to revise the proposal or to see an alternative from
someone else.  That leaves (2) and (4).

     Should Common Lisp support case-sensitive reading?

There are a number of applications that could make good use of the
Common Lisp reader except for one thing: the reader does not preserve
case.  I would like to help these applications.  In addition,
programmers who wanted to wanted to use case distinctions in code
would find it easier to do so.  You can regard this as an application
if you wish: there is a language very like Common Lisp only...

Common Lisp already allows the user to change the meaning of
characters by defining character macros, by changing the base
of numbers, and so on.  While some of these may be a bad idea,
character macros (at least) can be defended.  So I don't think
any arguments that apply just as well to character macros are
very compelling.

     New parameter or readtable operation?

Kent has argued well against the addition of a new parameter.
Any code that thinks it already takes all read parameters into
account would have to change.  So there is a potentially high
cost to users.

A readtable operation would involve only an existing parameter,
*READTABLE*.  However, if all we want is to set whether the reader is
case-sensitive or not, something that lets us have any character
translated to any other is arguably too powerful.  I don't want to
have a long debate about whether or not it's a good thing; and I can
imagine that some people might feel quite strongly that it is not.
Also, it's not a particularly convenient way to change case
sensitivity (though it's not all that hard).  However, a read table
operation that just changed case sensitivity seems strange.  The
number base isn't part of the readtable, so why should this be?
And should it be a keyword argument to COPY-READTABLE?  I wanted
(at least initially) to avoid such questions and to present a
proposal that seemed simpler (think, e.g., of what it would take
to write the test case).

I am willing to go either way, but I would like to know what
people think.  I would have presented more options in the initial
proposal, but I think it's best to have one option if we know it's
the only one we really want.


Responses to specific points follow:

> If case is -ever- to be significant, case must be preserved internally.
> [...]  CLtL indicates that this is true.

> If case is significant internally, then every symbol must have a
> well-defined internal casing in order to be found.

> An arbitrary choice must be made between whether CAR maps to |CAR| or
> |car|.

I agree.

> Some case had to be chosen. The arbitrary choice made was uppercase.
> Personally I think this was the right choice, but I recognize that others
> would have preferred lower.

The general trend is towards writing code in lower case.  The T
sources are now in lower case, Winston and Horn 3e uses lower case.
Both used to be upper.  I think it may have been shown that lower case
is easier (for most people?) to read.  Still, this is to a large extent
a matter of taste and not something that this proposal would change.

> [...] if you set *PRINT-CASE* globally, you don't interfere with the
> correct operation of libraries that others have written, 

That is true, but setting *READTABLE* does interfere with the correct
operation.  So this is not something Common Lisp has carefully avoided
so far.  Indeed, I think it is a good thing that the reader can be
used to read in other than the standard way, though perhaps not a good
thing that it is controlled by global parameters.

This line of argument would be better if the read table were one of
the arguments to read rather than controlled by a special variable.

> In spite of what I would characterize as superficial criticisms from
> people about Common Lisp and/or *PRINT-CASE*,

The criticism issue is a fairly complex one.  Some people make
wild claims about Common Lisp and cite "easy targets" such as FORMAT.
Often there is something reasonable behind the complaints, but it is
often difficult to find it out.  With fewer easy targets it would be
easier to get at the real problems, and wild claims would be harder
to make.  People would have to think harder.

Anyway, a number of reasonable people who are quite willing to use
Common Lisp have applications in which they could use a case-sensitive
reader.  They are often surprised to find that there's no way to do

> Your *READ-CASE* proposal is incomplete because the test case does
> not show the calling of a built-in function.

OK.  I'm not sure how much test cases have to cover.  There are
certainly other proposals that do not test every consequence.
Anyway, since it's dangerous to set *READ-CASE*, I rebound it
instead, since that is what I think people will do.

> Leaving aside issues of what would out and out break
> if you set *READ-CASE* to :DOWNCASE, you'd end up having to write 
>  (CAR Zebra)

That one must write CAR is mentioned in the aesthetics.

> A more technically reasonable alternate solution might be to extend
> *PRINT-CASE* to take a sort of alist as a value. Eg, consider:
>  ((ZEBRA . "Zebra") :UPCASE)

That seems to address a completely different issue (something about
output rather than input, it appears).

> I am also amenable to the idea of creating a portable way to modify
> the readtable to turn off case translation.

I am also amenable to that idea.

> Point #3 of the Rationale is, as I've discussed, not a problem but a
> feature. It's perhaps not as strongly motivated in the writeup as it
> might be, but I stand by it strongly.

I'm not sure what you mean here.  I don't think it's a problem that
Common Lisp has *PRINT-CASE*, but I do think it's a problem that
there's no way to control the way the reader treats case.

> My two counter-suggestions above are intended to
> help clarify the point that I am not objecting to your problem 
> description as unreasonable but rather to your solution as overly
> naive.

What I think is most suspect about my proposal is the attempt to
parallel *PRINT-CASE*.  I do not think the addition of a new variable
is necessarily unreasonable, since it is in some ways the simplest

> Also, following directly from my above remarks, your Cost of Users is
> drastically understated.

Very true.  I was not thinking clearly.

> The feature is not compatible since the very
> presence of *READ-CASE* would mean that programs would not snap together
> reliably if this variable were ever set. In practice, this would mean
> that any call to READ would have to be surrounded by a binding of
> *READ-CASE* just in case.

I think that's going a bit far.  After all, it's not now the case that
every call to READ is surrounded by a binding of *READTABLE*.

> One parting remark, I think the proposal name LIKE-PRINT-CASE is confusing.
> I would have expected that to mean `things typed in get downcased.' Only
> pragmatics would tell me this is ludicrous. 

I would have used NEW-PARAMETER (which is also perhaps ambiguous,
since it might mean an argument to PRINT) except that there were
several possible new-parameter proposals.

-- Jeff