Hey Mark, Thanks for the thoughts.
On Sat 27 Mar 2010 19:01, Mark H Weaver <[email protected]> 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/
