From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26914 invoked by alias); 1 Jul 2013 03:09:46 -0000 Mailing-List: contact kawa-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: kawa-owner@sourceware.org Received: (qmail 26899 invoked by uid 89); 1 Jul 2013 03:09:45 -0000 X-Spam-SWARE-Status: No, score=-3.1 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,KHOP_THREADED,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,SPF_PASS autolearn=ham version=3.3.1 Received: from mail-la0-f50.google.com (HELO mail-la0-f50.google.com) (209.85.215.50) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Mon, 01 Jul 2013 03:09:43 +0000 Received: by mail-la0-f50.google.com with SMTP id dy20so3852406lab.9 for ; Sun, 30 Jun 2013 20:09:41 -0700 (PDT) MIME-Version: 1.0 X-Received: by 10.112.130.37 with SMTP id ob5mr10747546lbb.77.1372648181187; Sun, 30 Jun 2013 20:09:41 -0700 (PDT) Received: by 10.112.73.143 with HTTP; Sun, 30 Jun 2013 20:09:41 -0700 (PDT) In-Reply-To: <51CE82FC.9090209@bothner.com> References: <51CE82FC.9090209@bothner.com> Date: Mon, 01 Jul 2013 03:09:00 -0000 Message-ID: Subject: Re: proposed changes to handling of false and end-of-list From: Matthieu Vachon To: Per Bothner Cc: "kawa@sourceware.org" Content-Type: text/plain; charset=ISO-8859-1 X-SW-Source: 2013-q3/txt/msg00000.txt.bz2 On Sat, Jun 29, 2013 at 2:47 AM, Per Bothner wrote: > A discussion on the kawa-commonlisp-dev list has suggested > we might want to consider some changes in Kawa's handling > of null, false, and the empty list. > > The high-level summary: > * Java null (#!null in Scheme syntax) would be considered false > (rather than true). I.e. in an expression (if c e1 e2) if c > evaluates to Java null *or* a java.lang.Boolean such that > c.booleanValue()==false, then e2 is evaluated; otherwise e1 is evaluated. > * The function null? would return true both of the empty list '() > (the value of LList.Empty) and Java null. All-in for this change, this is really a good move and will ease creation of conditional code that handles both #!null and #f construction at one time when checking for edge-cases. In my opinion, this will increase interoperability between Scheme and Java code > A linked-list may be > terminated by either '() (i.e. LList.Empty) or Java null. Lists > constructed using the Scheme reader or the 'list' function would > by terminated by LList.Empty as now. I'm less sure about this change, how would this work. If I understand correctly, writing `(1 2 3)` or `(list 1 2 3)` would have a '() as the last element. For the null part, I would I create such list. Something like this `(list 1 2 3 #!null)` would not end with a '() but rather a #!null ? > * Common Lisp, Emacs Lisp, and similar languages (which we will > call "Lisp") would represent nil using Java null (rather than as > now LList.Empty). Lisp would recognize the same values as "true" > as Scheme does; likewise for end-of-list. > * This change would have some negative performance impact, but > hopefully not much. > > The biggest motivation for this change is improved compatibility > with Lisp. This is similar to the solution adopted by Guile: > http://www.gnu.org/software/guile/manual/html_node/Nil.html > (We might consider implementing #nil as a synonym for #!null, > for Guile compatibility.) > This seems reasonable. But I'm unsure of all the implications for this change on my existing code base. Do you think this change would be fully backward compatible? > However, even if you don't care about Lisp, it probably seems > reasonable to consider Java null "false" rather than "true". > Allowing #!null as the end of a list may be less valuable, > but it does seem preferable for (null? #!null) to be true. > Totally right. > There are also some anomalies it would be nice to fix. > Java (and Kawa) allow you to create fresh java.lang.Boolean > objects: > (define-constant b1 (java.lang.Boolean #f)) > However, this object is considered true, not false: > (if b1 1 0) ==> 1 ; not (as one might expect) 0 > > Currently (if c e1 e2) is compiled to the equivalent of: > (c != Boolean.FALSE ? e1 : e2) > The proposal would change this to: > (isTrue(c) ? e1 : e2) > where isTrue is this library method: > > public static final boolean isTrue(Object value) { > return value != null > && (! (value instanceof Boolean) > || ((Boolean) value).booleanValue())); > } > > This is obviously slower; however, it is not as bad as it seems. > If the compiler determines that the type of the expression c > is 'boolean', then the generated code is the same as Java: > (c ? e1 : e2) > The Kawa type 'boolean' is the same as Java - i.e. a primitive > (non-object) type. > > For example: > (if (> x y) e1 e2) > compiles to: > (NumberCompare.$Gr(x, y) ? e1 : e2) > because NumberCompare.$Gr has return-type boolean. > The same is true of other predicates, comparisons, > and types tests. (Or at least it is supposed to be - > bugs may exist.) > > Finally, you can always optimize by hand. If you want > the old behavior (and generated code) you can always do: > (if (not (eq? c #f)) e1 e2) > Since both 'not' and 'eq?' are optimized this generates > the same code as (if c e1 e2) now does. > This is a good idea, it will be easier to think and reason about the code if a Boolean object false is considered as false in condition. It is all good from my point of view, even for the performance hit, that is not bad as it seems as you stated. > Comments? Does this seem like a worthwhile change? > Of course this is a not a simple one-line change, so > it would take a while (and some intermediate steps) > to implement fully. It's all for the best. I will probably be free to help either by testing the changes on my code base of by giving a hand with the implementation. > -- > --Per Bothner > per@bothner.com http://per.bothner.com/