The thing that impresses me most about Clojure is the community.
The excellent data structures and conceptual brilliance of the Lisp-reboot are all good things, but more importantly, you get the real sense that Clojure is in good hands, in active development by a core of top developers who care about the language and where it's going.
That in turn gives me confidence that Clojure will only improve over time.
Lisp is certainly great, and Clojure looks like a reasonable lisp. I wonder why the JVM attracts untyped languages while .NET attracts typed ones. Could it be that the Java language has damaged people’s ideas of what types are for?
Don't forget Scala, which is a strongly typed language in the tradition of ML or Haskell. Type-erasure in the JVM does limit what you can do with static typing somewhat but Scala is proof that it's quite doable.
[the following is apocryphal, citations needed] The difference in how .net and java implement generics is a big factor; Java implements them with erasure (basicly existing only at compile time), CLR tracks them on the runtime. This makes it very hard for languages on the CLR to coexist with other languages if they do not provide that parametric typing information. This is for instance the big thing holding up the CLR port of clojure itself.*
Re:static languages on the JVM, in addition to the poster boy scala, see http://mth.github.com/yeti/ an ML style language.
[ * i have no idea how the DLR and .net 4 stuff changes this situation ]
> This is for instance the big thing holding up the CLR port of clojure itself.
I have no idea about the hurdles Clojure on top of .NET is facing, but if it isn't ported by now it's more likely because Rich Hickey and the other core contributors don't have a strong interest for it.
The other problem would be that compatibility between the JVM/CLR versions would be affected.
> This makes it very hard for languages on the CLR to coexist with other languages
If you'll look closely, you can say the same thing about languages on top of the JVM ;)
You seem to have a much better handle on things than i so i'll take your word for it.
> I have no idea about the hurdles Clojure on top of .NET is facing, but if it isn't ported by now it's more likely because Rich Hickey and the other core contributors don't have a strong interest for it.
found a quote that i was thinking of when wrote that first comment
rhickey: cemerick: depends
cemerick: erasure is the best thing ever
cemerick: yeah; I caught a glimpse of what D. Miller is having to deal with
with ClojureCLR, and felt bad for him.
rhickey: cemerick: yes, people don't realize the huge tradeoff involved in
the CLR approach. It greatly complicates life for everyone, and is
a poor fit for dynamic langs
Interesting ... can you find technical details on that? ...
I guess the more static typing you have to deal with when generating bytecode, the harder it is for dynamic language writers.
Still, generics are used to great effect in the DLR for the call-sites inline caches ... like when you have a "doSomething(x, 2)" ... you know that "2" is an integer constant, and the generated call-site method that does the inline caching (to avoid hash-lookups) is using an "int" as the second parameter ... they can do that because method references are getting specialized so you can avoid boxing/unboxing for obvious cases, like passing integer/double constants.
[EDIT]
The MethodHandler from OpenJDK's invokedynamic proposal is a light-weight method reference, resembling System.Reflection.Emit.DynamicMethod from dotNet. MethodHandler will be used for call-sites and I think MethodHandler also gets reified.
The thing I don't like about the JVM are the inconsistencies ... you've got primitive types, but you can't define your own. Arrays are reified (and now MethodHandlers too) ... but you have no way to have your own reified generic data-structures.
Still ... in the long-run I think the JVM is a better platform than .NET ... if only Oracle would not stagnate it (or maybe now that it's open-source, some fork might be in order ... but I don't think it's doable unless it's a big company with lots of resources ... maybe Google, but I'm not holding my breath).
It's the JVM's and CLR's characteristics to blame.
Generics in .NET are said to be reified ... meaning that when instantiating a generic type, you get that type at runtime. It also handles it smartly ... meaning that you don't get performance penalties. And for stack-allocated objects (structs in .NET or primitive types like int/double) it does code-specialization (generates a new class) which means you can avoid boxing/unboxing overhead.
This actually makes a difference, as reified generics are the only sane way to have sane parametric polymorphism in a language that does runtime single-dispatch (like C# / Java).
Reified generics are hard to implement though, especially if you want covariance/contravariance. That's why .NET only has limited support for such rules (available only on interfaces and delegates).
With type-erasure, as in Java or in Scala ... generics are only a way to avoid explicit type-casts (Java), or to enable local type-inference (Scala). And I have found no paper on implementing reified generics on top of the JVM, without modifying the JVM (a possible task, no doubt, but it's probably not worth the overhead).
Java also has another problem (which is also a problem for dynamic languages) ... no way to have custom stack-allocated objects. This is a problem since number types (int/float/double) don't map 1:1 with the types in other languages, often having different behavior / different sizes, and this is a PITA since you want to avoid the boxing/unboxing overhead.
Of course, the CLR is not without its problems ... like, if you want lazy integers (as in Haskell) ... you would need an Union of an integer + a method reference, and it should be a union to avoid the memory penalty (and you could make the distinction by holding 1 bit of that integer as the tag). On the CLR, you can't do it this way since there are no union types, and the security model doesn't allow you to store method references inside integers.
The JVM on the other hand is preferred for dynamic languages because ... it is a better target (it does runtime optimizations that the CLR doesn't) and because people wanting dynamic languages also prefer more open ecosystems.
.NET's DLR is an interesting piece of work, but you don't gain much performance by using it and to me it seems like another mouse trap (no really ... building DLR ASTs seems like a good idea, but what happens when your language is nowhere close to Ruby/Python or Javascript, which have similar base types and dispatching rules?).
there were lots of comments about Headius' missing JVM features post: tagged fixnums, value types, continuations , lightweight coroutines. TCO, reified type info; unsigned int
The excellent data structures and conceptual brilliance of the Lisp-reboot are all good things, but more importantly, you get the real sense that Clojure is in good hands, in active development by a core of top developers who care about the language and where it's going.
That in turn gives me confidence that Clojure will only improve over time.