Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Someone mentioned the JVM interop of Clojure is it's main selling point. While its definitly awesome to have that great integration (I'm a heavy interop user), for me, the main strength is having persistent data structures at its base for everything. I myself played with the thoughts of creating a native runtime based on Clojure's syntax and data structures. I cant see that this project uses persistent data structures. Am I wrong? please enlighten me.


> for me, the main strength is having persistent data structures at its base for everything.

Agreed, but also:

- The ISeq abstraction

- Software Transactional Memory for state management

- Structure-sharing of the persistent structures, for added efficiency/performance

And of course, all the nice reader macros that make things so much easier to read.

This project is cool, but what I'd rather see is Clojure becoming parasitic, living on all the host VMs it can. We've got the CLR version, and ClojureScript for V8/JS, but we could also have it properly on top of Python, Ruby[1], Lua, Erlang, and LLVM.

[1]: I know Rouge exists, but I'm not sure how well it's progressing.


Clojure itself would also love to become parasitic just as you described. It's actually one of it's explicitly stated goals if I'm correct.

Apparently implementing Clojure on the LLVM is no easy feat though; judging from references to previous discussions on the mailing list. [1] There is some work on it already though [2,3,4] and I'm sure we'll get there eventually.

[1] https://groups.google.com/forum/#!topic/clojure-dev/bex25u9h... [2] https://github.com/ohpauleez/cljs-terra [3] https://github.com/halgari/clojure-metal [4] https://github.com/halgari/mjolnir


I would say it is also a matter of focus.

A real compiler backend takes a bit more than a weekend project, and it is hard to know the real reasons, technical or personal life of the coders, for the current state of the projects.


I think the real problem with the native Clojure compilers is that Clojure is designed to be symbiotic with host platforms that offer a much higher level of abstraction. For example, to perform well, all those persistent data structures require an advanced garbage collector. The JVM, the CLR, and the leading JavaScript implementations offer this; it would take a lot of work to implement one in the absence of one of these mature platforms.


> Structure-sharing of the persistent structures, for added efficiency/performance

I think the structural sharing is the definition of persistent data structures, as distinct from immutable data structures in general.


> I think the structural sharing is the definition of persistent data structures, as distinct from immutable data structures in general.

Oh, yes, you are very much correct. I just wanted to highlight that is itself a feature of Clojure's behavior.


Not directly, but nearly. Structural sharing / copy-on-write is basically the only way to satisfy the actual definition.


ISeq is considered to be harmful, because partly due to ISeq over use Clojure's code is cluttered with unnecessary and costly (making a new copy) "casts" (or what a proper clojurian term for this?) from one kind of a container to another. There is an opinion that classic lists, sequences (only on lists, vectors and strings) plus series are good-enough.


STM/Refs are not really used in the Clojure community, its a great a concept but in practice almost no one uses it, at least that's what you can see from public Clojure projects.


At some point most applications have to have some state. Most clojure projects are nice functional libraries that work without state but somewhere are one or to refs (or atoms). A good example is Datomic where Rich Hickey said, it only has 6 refs. Its 99% persistent but somewhere you need at least a pointer to your current state. Of course you can push the problem to your database or some libraries but I really like refs with their optimistic locking and am using them to have in-memory consistency.


Wouldn't you generally want an STM in your domain model in places where it's essential rather than in (ideally generic) open source libraries?


Currently, vectors are the only real data structures; they're naively persistent: operations like rest and cons create a fresh copy (I haven't implemented COW yet). I'm not quite sure how to implement it for `setq` though (a feature not present in Clojure, but something that's necessary for building an editor like Emacs): when a variable is set to a new value, where is the reference to the old variable, for gc and access?


>> ... `setq` though (a feature not present in Clojure...

I am not familiar with elisp but from first google result it reads that the equivalent is alter! / swap!.


Only special ref objects are mutable in Clojure (via STM). I was talking of `setq` in the context of mutating normal variables. It's perhaps a bad idea, and I have to study how LT manages its plugin system without mutation.


You don't have to mutate them. You can create a new persistent variant and just mutate the ref to point to the new one. Users of that "variable" store the ref instead of the value (well, actually, they get the choice of which to do). If users have held on to references to the old values, the GC doesn't collect them. If they haven't, the GC can collect them just like any other circumstance involving persistent data structures.


Actually, you can have real mutable variables as fields in a type, although you should think twice about doing so in practice as mutable variables are often not the solution. But here's an example!

(deftype SomeTypeWithMutableFields [^:unsynchronized-mutable some-mutable-field ^:volatile-mutable another-mutable-field])

:unsynchronized-mutable corresponds to a normal mutable Java variable, and :volatile-mutable corresponds to a Java variable with the volatile modifier.

They are private by default, you can only set! them within the lexical scope of the deftype definition. If you needed to expose fast host mutation to the public, I would create a setter/getter interface (via definterface) and implement it on your deftype and use set! locally to mutate the field there.


JVM as primary target is the main selling point, just watch author's talks. Back then Rich Hickey described JVM as "the default platform of choice" for "serious development" (read - corporations). OK, I am paraphrasing a bit, but he explicitly praised JVM.)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: