On Jun 19, 2010, at 15:58 , Rich Hickey wrote:
> I am telling you though, if you continue with these "show stopper", "will
> keep people from using Clojure" sky-is-falling histrionics, I will stop
> reading your messages.
My apologies here, simple reason is I love clojure and it is one of the best
(IT wise) things that had happened to me in a long time (actually since I
bought my first Apple but that is a different story). I personally for my own
code am very much fine with everything and will hardly leave for something that
will hardly ever affect me (sorry to disappoint people here). I simply want the
best for clojure since I hope for many more people to feel the joy and fun I
had when I first discovered clojure, that is why I argue strongly against
changes that, in my eyes will take this from those people simply in the fear
that when I explain one of my friends how great clojure is (and it certainly
is) they will look oddly at me and tell me 'wait this isn't great this is
confusing and frustrating.' I can't guarantee this will happen and of cause
this is just an argument but this is what I fear. I actually wanted to explain
a friend who is very new to clojure (but a quite versed programmer) why I'm so
eager in this matter and I seriously had a problem to explain him what is so
confusing because the mix of static and dynamic typing and why loop acts like
this was very hard to explain without starting from a very low level and
explain clojures inner workings with numbers, loops, recurs and types. But I'll
try to keep things a little bit less enthusiastic I promise :).
That said I think we're currently arguing three topics intermixed and this
might lead to some confusion, at least I see the two big topics here which are
not entirely mixed but interact in some areas.
1) The behavior of auto promoting of operators.
2) The default type of literals (primitives vs boxed).
3) The behavior (and typing) of loop.
To 2)
I think at least 2 is quite separated from the other two issues. When I'm not
wrong we can have primitive literals without loosing anything at all, just
being faster until they need to be boxed (unless I overlook something).
To 1)
At 1 I wonder could we have auto promoting but only if it becomes required? As
in (+ 1 1) returns (long 2) but (+ 100000000000 1000000000000) returns a boxed
value? This would I think give us fast arithmetics as long as we use small
enough values but graceful behavior when we need big math? Or will this again
slow things down a lot? If this would be a compromise for a semi fast but still
non breaking (as in throws) way how about this as default and +' as the version
that enforces fast math and won't ever promote but throw where it really really
matters?
To 3)
To the third thing and in my eyes this is the most challenging and problematic
issue. loop in current clojure is not statically typing (of cause it is but it
tosses objects in any field so you can pass whatever you want and it still
works). The current qual branch introduces silent (implicit) static typing if
you use primitives this in my eye can lead to a lot of confusion and requires
the user to know a lot about clojures under the hood to safely use recur.
Some people complained 'there are no /real/ breaking examples' and that is
true, there aren't because the use of loop itself is very rear I think most
people either use the list functions or laziness instead of recur. Also people
who use loop recur in a mathy way (where problems might arise due to lot of
number handling) are either beginners who write try out code as the fact
example commonly shot down for being 'not real' or people who very much
know-what-they-do<tm> and will most likely already have type hinted their code
to squeeze the speed out of it so neither will it break nor will they
experience a speed improvement.
My dream would be that loop would 'just work' and 'just work fast' too, of
cause this isn't easy. Generally two ideas spring to mind and were already
mentioned. One being compiling the loop twice (I write it in pseudo code here
since I am not sure how clojures compiler works, I tried to read the loop part
but I got confused :P):
(loop [n n r 1]
(code ..)
(recur (f n) (g r)))
#loop label <object n object r>
... loop code ...
recur new-n new-r
#loop label <object n long r>
... loop code ...
recur new-n new-r (overloading the loop label r could either be long which
would jump to the fast version or not long which would jump to the object
version).
I am entirely not sure if this is possible or not, but if it were heck this
would be a nice way to go ^^. To solve the problem with too many variables I'd
not go with one overload for every possible combination but one overload with
all objects (old way) and one overload with everything nice fast primitive
types - meaning that when one primitive fails all of them have loose their
primitiveness.
Another option would be as someone above I'm not entirely sure who any more,
suggested that instead of the compiler warning about not returning a primitive
the loop just would box that primitive and toss a warning if warn on reflection
is set to true - this would be fast where the compiler can decide it is
correct, never wrong, and quite easy findable and optimizable due to the
reflection flag.
Regards,
Heinz
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en