The arguments seem to be winding down, so I thought this would be a
good time to summarize my thoughts.

My favorite option of those proposed is:
+, *, -, inc, dec auto-promote.
loop/recur is changed so that primitive bindings are boxed.
+',*',-',inc',dec' give error upon overflow.
A new construct, loop', is introduced that doesn't box primitives and
enforces recur with primitive upon penalty of error.

Why I like this:

*  Ordinary code continues to work almost exactly as before (no new
surprise errors from overflowing longs or incorrect loop/recur usage),
and with similar performance characteristics (and I already consider
Clojure to be quite fast among dynamic languages).  [Note that
changing loop to auto-boxing behavior shouldn't hurt performance
because currently, almost all numbers are boxed unless otherwise
specified with an explicit primitive typecast, so we're already seeing
what "boxed speed" looks like].

* The recipe for optimization is simple.  Declare your function to be
static and type hint the primitive inputs and output.  Inside your
static function, change all +,-,*,inc,dec,loop to
+',-',*',inc',dec',loop' and you'll get great speed improvements with
much less effort than before.  [Maybe through some clever macrology,
you could create something called defn-optimize which combines the
static function definition with a rebinding of +,-,*,inc,dec,loop to
their "prime" counterparts within the body of the static function,
since these constructs are likely to be all used in conjunction with
one another and are the most natural choice within a static function.]

* I believe that it makes the most sense to make the auto-promoting
ops the default because the non-promoting ops only provide benefit
when all the inputs are primitive longs.  Since numbers become boxed
whenever they are stored in a collection or passed to or returned from
a non-static function, it seems likely to me that except in certain
local contexts (for example, within a static function whose inputs are
declared to be primitive, or within a loop), most numbers will
eventually become "contaminated" by boxing anyway.  So I think it will
be easier to annotate those special instances where it is clear from
the local context that you're dealing with all primitives, rather than
the other way around.


I have this preference even though I am not using bigints in any of my
production code.  Except when I'm playing around with Project Euler
problems, most of my code is not particularly numeric in nature.  But
I still feel that the auto-promoting/auto-boxing defaults will provide
me with much less cognitive burden.  I don't want to worry about what
types of numbers are flowing into and out of the various calls and
loops to make sure that something will work the way I expect.  Types
are mostly "hidden" in Clojure, so it's difficult enough to analyze
this flow in one's own code, and it would certainly be even harder to
figure out what's going on when reading someone else's code.

The #1 reason I code in Clojure is that I find it easy to express
complex concepts in ways that are easy to understand and easy to
verify.  For me, keeping that clarity is paramount.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to