I believe that the last sentence is not entirely correct. It is
effectively UNSPECIFIED, whether or not the empty list is the false
object or not. I recall Dr. Wilson pointing this out already some
time ago. Please see the excerpts from R4RS enclosed for easy
reference below.
>We would very much like to find an arrangement that allows all Emacs
>Lisp code to run unchanged, allows all R4RS code to run unchanged, and
>allows the two to communicate mostly transparently.
>None of the obvious compromises work nicely.
IMHO, the last sentence is not entirely correct either. If Guile
implements
(eq? '() #f) ==> #t
then
(0) `eq?' can be implemented by single pointer comparison
(1) Guile is R4RS-compliant Scheme (in this respect)
(2) all _portable_ R4RS Scheme code runs unchanged (in this
respect)
(3) communication with Emacs Lisp is straightforward
(in this respect)
(4) both constructs
(if (null? foo) ...)
and
(if (foo) ...)
can perform to a single pointer comparison (and similar
efficiency is achievable for possibly frequent constructs
involving `and', `or', etc. in both boolean and list
contexts). Indeed, function `null?' can be just a redundant
identity in context of `if', `and', `or' special forms
(5) situation is analogous to common C language idiom
if (foo)
{ ...
where foo is an integer (see K&R, Second Edition, p. 42, last
three paragraphs of section 2.6). Note that Guile is targeted
on _C programmers_ and such an audience (I guess) should not
have any conceptual difficulties to live without "pure", or
isolated, or orthogonal, boolean type
(6) possibly esoteric problem whether various default values
be #f or `() are made irrelevant and one class of errors is
made nonexistent
(7) (conceptual) compatibility with all other lisps is
maintained (in this respect).
Is it not an example of "obvious compromise working nicely"?
>Modifying either language to match the other breaks existing code in
>ways that are impossible to fix mechanically.
There may exist perfectly legal R4RS code running under a specific
R4RS-compliant Scheme that assumes
(eq? #f '()) ==> #f.
There may exist perfectly legal R4RS code running under a specific
R4RS-compliant Scheme that assumes
(eq? #f '()) ==> #t.
Given R4RS, it is NOT possible to create R4RS-compilant Guile which
does not break at least one of the above codes. Thus, the goal NOT to
break ANY R4RS Scheme code is not achievable.
However, any _portable_ R4RS Scheme code does NOT make an assumption
either way and therefore Guile will NOT break it if
(eq? #f '()) ==> #t
is adopted. Also, Guile will NOT break straightforward Emacs Lisp
compatibility (in this respect). And also, neiter efficiency nor
clarity of design will be jeopardized.
>I'm told some people like to write Scheme functions that return either
>a (possibly empty) list, or #f to indicate some sort of 'other' case.
This is NOT a R4RS-portable code (i.e., this is not guaranteed to run
correctly in any and all of R4RS Scheme implementations). I as a
layman do not dare to assess whether or not this is an example of good
programming practice.
Nevertheless, I guess it is not too demanding to expect Scheme
programmers to refrain from such practices if they desire their code
run under several R4RS Scheme implementations, including Guile. IMHO,
it can be expected from them with the same (or larger) ease as it can
be expected from them to honor (perhaps optional?) case-sensitiveness
of Guile. Or, is there any qualitative difference between portability
considerations in these two cases?
>Can this be implemented efficiently?
>
>I think so. `eq' can use fast, approximate tests to cover most common
>cases, and then fall back to a slower, correct function for the rest.
>Something like this might be useful in the Emacs C code:
>
> #define EQ(x, y) ((x) == (y) \
> || ((((x) ^ (y)) & MASK) == 0) && lisp_eq ((x), (y)))
>
>where MASK has very few zero bits, and the elements of the equivalence
>classes have representations differing in only those bits. The '=='
>clause will catch most cases when EQ is true; the '^' clause will
>catch most cases when EQ is false; and the lisp_eq function will be
>always correct, but relatively slow.
To be compared with:
#define EQ(x, y) ((x) == (y))
The latter is not only faster but also conceptually simpler.
>I think this arrangement meets the needs of most of the Guile
>audience.
>
> - Emacs Lisp programmers want their existing code to work when
> Emacs switches over to Guile. They won't notice a thing.
> - Some Scheme programmers want to use Guile as an ordinary Scheme
> interpreter, to take advantage of its debugging and systems
> programming features. They won't notice a thing.
> - Some Scheme programmers want to program Emacs in Scheme.
> There is no legacy of Scheme-for-Emacs code that we care about, so
> these people will deal with whatever we give them.
> - Programmers writing new applications using Guile should be happy,
> too. There is almost no extant Emacs Lisp code which doesn't use
> buffers and other Emacs-specific data types; any Emacs Lisp code
> they want to use in their application will need porting anyway.
The counter-proposal, i.e., `(eq? #f '()) ==> #t', satisfies all of
the above statements.
>Appendix: Why not just fix all the Emacs Lisp code?
Why not just do the easiest thing possible? Why not just identify
`#f' with `'()' in Guile?
I have probably missed something important. I do not understand why
is would be of considerable advantage if Scheme specification evolve
into a REQUIREMENT of `(eq? #f '()) ==> #f' in the future.
Could somebody please summarize the ADVANTAGES of having #f and '()
distinct?
Are these advantages sufficient to justify the effort? Do they
justify the complications in the Guile specification and
implementation? Do they offset the advantage of seemless interaction
with Emacs Lisp (in this respect)? Are they worth the current
discussion?
Thank you.
-- Petr Adamek
EXCERPT FROM R4RS
[from r4rs/procs.tex:]
\section{Booleans}
\label{booleansection}
The standard boolean objects for true and false are written as
\schtrue{} and \schfalse.\sharpindex{t}\sharpindex{f} What really
matters, though, are the objects that the Scheme conditional expressions
(\ide{if}, \ide{cond}, \ide{and}, \ide{or}, \ide{do}) treat as
true\index{true} or false\index{false}. The phrase ``a true value''\index{true}
(or sometimes just ``true'') means any object treated as true by the
conditional expressions, and the phrase ``a false value''\index{false} (or
``false'') means any object treated as false by the conditional expressions.
\vest Of all the standard Scheme values, only \schfalse{}
% is guaranteed to count
counts as false in conditional expressions.
% It is not
% specified whether the empty list\index{empty list} counts as false
% or as true in conditional expressions.
Except for \schfalse{},
% and possibly the empty list,
all standard Scheme values, including \schtrue,
pairs, the empty list, symbols, numbers, strings, vectors, and procedures,
count as true.
\begin{note}
In some implementations the empty list counts as false, contrary
to the above.
Nonetheless a few examples in this report assume that the
empty list counts as true, as in \cite{IEEEScheme}.
\end{note}
% \begin{rationale}
% For historical reasons some implementations regard \schfalse{} and the
% empty list as the same object. These implementations therefore cannot
% make the empty list count as true in conditional expressions.
% \end{rationale}
[from r4rs/basic.tex:]
\section{True and false}
Any Scheme value can be used as a boolean value for the purpose of a
conditional test. As explained in section~\ref{booleansection}, all
values count as true in such a test except for \schfalse{}.
% and possibly the empty list.
% The only value that is guaranteed to count as
% false is \schfalse{}. It is explicitly unspecified whether the empty list
% counts as true or as false.
This report uses the word ``true'' to refer to any
Scheme value that counts as true, and the word ``false'' to refer to
\schfalse{}. \mainindex{true} \mainindex{false}
\begin{note}
In some implementations the empty list also counts as false instead
of true.
\end{note}
\todo{Bartley: tighten this up.}