[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: guile and elisp
From: |
Andy Wingo |
Subject: |
Re: guile and elisp |
Date: |
Sun, 28 Mar 2010 14:13:37 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/23.0.92 (gnu/linux) |
Hey Mark,
Thanks for the thoughts.
On Sat 27 Mar 2010 19:01, Mark H Weaver <address@hidden> writes:
> (BTW, I'm deliberately writing "lisp" instead of "elisp" because these
> discussions should be relevant to any lisp dialect that uses nil for
> both false and eol, and in the future guile might support other
> lisps).
Sure, good point. Scheme is still a lisp, so it helps me to write
"elisp", but I'll try to parse your statements appropriately :)
> On Sat, Mar 27, 2010 at 05:54:24PM +0100, Andy Wingo wrote:
>> I'm not sure (I keep saying "not sure", and I'm really not :) that
>> *value* or *identity* is the way to solve this problem. To me the
>> question is more of *property* -- is this value false, is it equal? to
>> another, is it a boolean, etc.
>
> Well, if we can assume that all non-lisp code in the guile system will
> robustly handle nil by using the appropriate predicates, then yes,
> that's a fine solution with clear semantics. I just don't think
> we can safely assume that.
Note that we have the same problem on the Scheme side, for code that
assumes that (not x) implies that x is eq? to #f. I don't want to change
eq?, so this hole will exist. But, at least it's a documentable hole,
and we can fix up any code that needs it without e.g. introducing the
concept of #f-but-not-end-of-list into elisp itself, likewise avoiding
introducing the concept of #f-or-end-of-list into Guile.
Which reminds me: another breakage point would be the canonical:
(cond
((null? x) ...)
((not x) ...)
...)
The result if x is nil depends on the ordering of the null? and not
clauses.
> Someday there may be significant libraries and other complex software
> developed elsewhere being used in guile-emacs. Most code outside of
> the lisp world has never had to cope with an ambiguous "maybe boolean
^^^^ Scheme?
> false or maybe the empty list" value. When that code meets the lisp
> world, I guarantee you'll start seeing obscure bugs crop up. The
> system as a whole will not be as robust as it could be.
Of course you're right. I've just been thinking that all solutions will
have this characteristic to greater or lesser degrees.
> A lot of code outside of lisp uses equality to test boolean values.
> If nil is distinct from #f, then that code will fail.
Such code is in poor style IMO; changing it to use the predicates would
make it cleaner and more correct. Not sure how much code would fall
under this case.
> A lot of code assumes that if a value is boolean, then it cannot be a
> list, and vice versa.
Yes. But what can you do? Not all nil values are actually one or the
other.
> Some code looks up booleans and/or lists in hash tables or other
> structures. That code won't deal gracefully with list structures
> containing nil.
Ah, but it will! There are three cases here, sets with eq?, eqv?, and
equal?. Eq? sets, and to an extent eqv? sets, are designed to return a
value if the key is the actual value that was passed in.
So the key is an opaque value, and it doesn't really matter what it is,
because e.g. (memq x set) won't inspect what x is. X must actually *be*
the object that was inserted into the set; it doesn't matter what type
it is.
A similar argument applies to equal? maps/sets. If you inserted X into a
set, and call (member x set), then the call succeeds, as with eq? sets.
This only leaves the case in which you put X in, then construct a new Y
that should be equal? to X, and call (memq y set). Here's the kicker: if
X was constructed in elisp and contains a nil, and Y was constructed in
Scheme out of Scheme data and thus does not contain a nil, *they aren't
the same*. Not to Scheme anyway!
Of course elisp's equal? sets might operate differently, as I mentioned.
> Some object-oriented languages may overload an operation depending on
> whether a parameter is a boolean or a list. I don't see how such code
> can deal with nil gracefully without being significantly rewritten.
Well, specifying on lists involves an O(N) calculation at method
dispatch time, so it's not a good idea; but with '() versus #f, GOOPS
can specify one is more specific than the other, but also provide a
protocol to override that default.
> Using your proposed intransitive equality predicates would handle many
> of the common cases properly, but not all of them.
I probably was unclear, but I've decided that intranstive equality is a
worse idea than (equal? '() nil) => #f. (For elisp though, (equalp '()
#f) => t, so equalp can be permissive and transitive.) I would suggest
making equal? in Scheme behave as eq? for booleans.
I don't think that deprecating nil is really an option, because some
nils really are lists and booleans. But I could be wrong on this point,
as on many others!
(More thoughts? :)
Andy
--
http://wingolog.org/