From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Andy Wingo Newsgroups: gmane.lisp.guile.devel Subject: guile and elisp Date: Thu, 25 Mar 2010 13:22:25 +0100 Message-ID: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: dough.gmane.org 1269525381 31336 80.91.229.12 (25 Mar 2010 13:56:21 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Thu, 25 Mar 2010 13:56:21 +0000 (UTC) To: guile-devel Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Thu Mar 25 14:56:16 2010 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1NunXd-0001f9-Uv for guile-devel@m.gmane.org; Thu, 25 Mar 2010 14:56:16 +0100 Original-Received: from localhost ([127.0.0.1]:51598 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NunXZ-0001la-1o for guile-devel@m.gmane.org; Thu, 25 Mar 2010 09:56:05 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NunUn-0000eB-NB for guile-devel@gnu.org; Thu, 25 Mar 2010 09:53:13 -0400 Original-Received: from [140.186.70.92] (port=35289 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NunUi-0000Z4-0w for guile-devel@gnu.org; Thu, 25 Mar 2010 09:53:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1NunTU-0007xM-Jf for guile-devel@gnu.org; Thu, 25 Mar 2010 09:52:00 -0400 Original-Received: from a-pb-sasl-quonix.pobox.com ([208.72.237.25]:45350 helo=sasl.smtp.pobox.com) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1NunTU-0007tq-Gm for guile-devel@gnu.org; Thu, 25 Mar 2010 09:51:52 -0400 Original-Received: from sasl.smtp.pobox.com (unknown [127.0.0.1]) by a-pb-sasl-quonix.pobox.com (Postfix) with ESMTP id 16AFAA596A for ; Thu, 25 Mar 2010 09:51:24 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=pobox.com; h=from:to :subject:date:message-id:mime-version:content-type; s=sasl; bh=G g8FQC2zcDINh1dP9a3E1fye08g=; b=LRa4OjsDM7d/XISqWBJzF8DKFCKTggXUq 2s87LyHboZmCy8XRFafxPeKeCTo26ZYiCTj/SuT7Q9/JQsq4ba990w29walhVb7I X11/JbDHQ4x+FvLwVm5xSU1fZ7nIB43aNczVE6iyLMGY+U1/M1jd7YNZcGaJrVwJ JV1pxVUzmU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=pobox.com; h=from:to:subject :date:message-id:mime-version:content-type; q=dns; s=sasl; b=ERx YH61km1+0gP8BCv/Z9EMVHaMWMlHFViKVW0Zqib5s0tsNkQj4uQul7+ZAboTFPmo ciKe4VGSW+jRK7UrrpeOVrDjfZE33sGOxUW4BcWcG9TNGiC9UQZJP29Yy4Gk6b+l eGmztCUZgf8fxvceaziFz2cpO61/VV8CvIbLkmro= Original-Received: from a-pb-sasl-quonix. (unknown [127.0.0.1]) by a-pb-sasl-quonix.pobox.com (Postfix) with ESMTP id 09B4AA5969 for ; Thu, 25 Mar 2010 09:51:23 -0400 (EDT) Original-Received: from unquote (unknown [88.17.131.151]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by a-pb-sasl-quonix.pobox.com (Postfix) with ESMTPSA id DAD7FA5968 for ; Thu, 25 Mar 2010 09:51:22 -0400 (EDT) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.92 (gnu/linux) X-Pobox-Relay-ID: 8018378E-3815-11DF-8AB0-D033EE7EF46B-02397024!a-pb-sasl-quonix.pobox.com X-detected-operating-system: by eggs.gnu.org: Solaris 10 (beta) X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:10080 Archived-At: Hi all, For 2.0 I have a very short list of things to do, mostly documentation and compatibility work, but there is at least one feature: finishing Mark Weaver's integration of nil into Guile. If you're just catching up, Elisp has "nil", which is both false and the end-of-list. Nil works fine in Elisp, but we would like to tightly integrate Scheme and Elisp, allowing procedures and data to be passed back and forth -- so we need a way for Scheme to see nil as false. So! Here's a table of how various functions respond to various inputs. To make the table more readable, a result of #t is written as T, and a result of #f as F, and nil as NIL. #t #f '() nil otherwise Scheme: boolean? T T F T F not F T F T F null? F F T T F Elisp: booleanp T T T T NIL not (elisp) NIL T T T NIL I guess I was assuming from the get-go that elisp's T would be Scheme's #t; one could decide otherwise, but that would be pain for no gain. So already we see how practical considerations are creeping in :) Currently in Guile, things are as the table describes; though it could be that the elisp functions return F instead of NIL. But the whole point here is to allow Elisp to see #f as nil, so I'm not particularly worried about this. (I'll be writing test cases according to these tables). One can see however that introducing a value to which e.g. BOOLEAN? or NOT respond differently than the "otherwise" case can break code that assumes that, for example, `(not foo)'` implies that `foo' is #f (whereas in the future it can be nil also). We don't see these cases now, because we aren't mixing Scheme and elisp much. But I would argue that that code is broken; that it should test for /properties/ via the NULL?, NOT, etc instead of testing for values. More tricky is what should happen with equality predicates, and the fallout thereafter. We could make any decision here; but here's one set of decisions: EQ? #t #f '() nil #t T F F F #f T F F '() T F nil T This table shows the result of calling `eq?' between these four values, specifically that #t is only eq? to #t, #f to #f, and so on. The missing half of the table is redundant. EQV? could be like EQ? or like EQUAL?; I am inclined to make it like EQ?. So, same considerations for EQV?. But what about this one: EQUAL? #t #f '() nil #t T F F F #f T F T '() T T nil T If we disregard #t, because it's not interesting, and cut out the identity cases, we get the following three rules: (equal? #f '()) => #f ; required by scheme (equal? #f nil) => #t ; interop (equal? nil '()) => #t ; interop But then you break the transitive property of equality! [An aside: This equal? behavior would require `hash' (not `hashq' or `hashv') to hash #f, nil, and '() to the same value, then to be distinguished via `equal?' while traversing the bucket. I don't think `hash' presents more problems than that.] *** What to do? In a perfect world, we want '(a b c . #%nil) to be EQUAL? to '(a b c . ()). But as I showed above, we can't do that without breaking some corner cases. It's of course an option to just make `(equal? #f nil) => #f'. But this would limit the interoperability of Scheme and Elisp. I was telling this to our fringe languages group last night, and Andrew Bagdanov remarked that it would be amusing if opaque types like buffers were more interoperable than pairs. It would also be an option to translate data from Elisp to Scheme and back, when going across the language barrier, but this pains me on many levels; it destroys EQ? semantics, and it changes algorithmic space/time complexities. Another option would be to present an abstraction above pairs, or sequences in general, as Clojure has done. (Incidentally, this decision, combined with support for lazy sequencies, led Hickey to remove the concept of nil-as-singleton from his language.) These are the four options that I see. For myself, the interoperability benefits of considering '() as equal? to nil are quite compelling, and outweigh the practical implications of the transitive equal? wart. But, I wanted to mention this analysis and these options so that interested people can give feedback, and we can document our decision. (Actually, thinking on it a little more, maybe it would be the right thing to do to just keep nil not equal? to #f. But it's a complicated question, and my brain is tired :)) Thoughts? Happy hacking, Andy -- http://wingolog.org/