Clojure on the other hand compelled me enough to learn lisp and emacs.
Beside the obvious: cloture is a parliamentary procedure to end debate on a subject, and I would like to end certain debates. Yes, Common Lisp is “modern.” Yes, Clojure is a Lisp.
While this doesn't actually explain why the person started the project itself, it does shed light on one possible explanation.
I'd also like it to conform well enough to the JVM implementation that I could use my full-blown Lispy Clojure for development, and still deploy with confidence on the JVM Clojure.
Obviously, someone's going to want to know what I think is missing from Clojure, so following is a partial list. These are things I've been accustomed to relying on for decades now, and that I always miss keenly when working with Clojure.
Instant startup with my environment already customized to my specifications.
Comprehensive reflection with full UI support. Support for inspecting absolutely everything in the runtime, with the ability to interactively edit everything you inspect.
The ability to reproduce my whole development environment and its entire dynamic runtime state on a different account or machine simply by copying over a file.
A real Lisp repl that can inspect and redefine everything in memory, save and restore the complete dynamic state of the running system, and deliver a finished executable from an expression typed at the repl. In short, anything you can do with the Lisp, you should be able to do from within the Lisp, by evaluating an s-expression at the repl.
Proper Lisp-style error-handling. The ability to catch any error or exception in an interactive breakloop, walk up and down the call stack, inspect and modify variables, types, and functions, and resume execution with the changed definitions just as if the pending function had been called with them in place originally.
People rightly complain about Clojure's atrocious error messages. They've gotten better, but they're still very far from what I expect in a Lisp error-handling system. I want the real thing: when something unexpected happens you get a proper Lisp-style interactive breakloop from which you can see and modify everything on the call stack and, indeed, everything in the running system, and you can tell the runtime where to resume execution from, either interactively or under program control.
A runtime designed with the understanding that you're going to be writing your application by changing it while it runs. Lisp and Smalltalk have had these features forever. Apple's Dylan and SK8 had them. It's disappointing that Clojure doesn't.
Common Lisp, for example, defines a standard protocol that enables you to redefine classes with the confidence that the Lisp will automatically update any existing instances to conform to the new definition. When Lisp can't figure out how to make things consistent, it doesn't quit or spew a dead stack trace; it starts a breakloop that captures the pending call stack. As I mentioned before, you can use the breakloop to inspect everything on the stack, make whatever changes are needed, and then resume computation with the changes in place.
I wish it were as easy to subsume foreign type systems into Clojure as it is in Common Lisp. Clojure's Java interop is good, but it's special. You have the nice Java interop, but you don't have a standard API for building your own equally-nice interops. Compare with Clozure Common Lisp's Cocoa interop. It's also good, but more importantly, it's built on common APIs (CLOS and the MOP) that you can use to make your own interop subsystems that are just as good.
To me, these are table stakes for a Lisp. I've already had them for decades. Working in Clojure means I have to give them up, and the whole time I'm missing them. A Lisp that doesn't know how to do them is only part of a toolbox. Whole drawers of essential tools are missing. I mean, sure, you can build apps with them. And you can build a house with stone knives and bearskins, but if you've used a proper toolbox before, you'll be missing it the whole time.
If there were a Clojure implementation with these features, then I wouldn't miss Common Lisp so much the whole time I'm working in Clojure. I probably wouldn't spend as much time looking forward to when I can get back to using a real Lisp. I'd get more done faster and with greater joy in my work.
I'm sort of hoping Cloture will turn out to be a step in the right direction.
Some Java:
public class Main {
public int addTwoNumbers(int a, int b) {
return a + b;
}
}
Calling it from ABCL: (defun void-function (param)
(let* ((class (jclass "Main"))
(intclass (jclass "int"))
(method (jmethod class "addTwoNumbers" intclass intclass))
(result (jcall method param 2 4)))
(format "calling addTwoNumbers(2, 4): ~a~%" result)))
Calling it from Clojure: (defn f []
(prn "calling addTwoNumbers(2, 4): " (.addTwoNumbers (Main.) 2 4)))
Note that the Clojure version creates the object, and the ABCL version doesn't do that for you; you still need to instantiate a Main yourself.There was briefly an attempt by Raphael Amiard to compile Clojure to Lua, which could also test this theory, but it was never completed and I doubt anyone else feels like doing that much work for free:
Alternatively I could spend some time assessing rutils or some other fundamental extension library... I'd like, one day, for one of those to gain a good tutorial and a bigger mindshare in the community.
Quite handy, it turned out.
I thought about extending the reader to allow for clojuresque applicable dicts (racket allows for this quite easily), but I never got to it.
https://github.com/oracle/graal/blob/master/substratevm/LIMI...
Where SBCL just adds some compiled code, writes a memory dump out in a second. Then this can be run as a new SBCL with added code - it still includes the compiler, and all other stuff. One can also then add more code and write another image... The new image is just like the other one, just with more code and otherwise the usual feature set.
This includes the whole SBCL and my code, not just a static application with limited dynamic features.
Many Common Lisp systems have a way to write a snapshot of the developed environment, which then starts in subsecond.
Additionally some Common Lisps have ways to do application or shared library delivery, which can remove dynamic features, remove parts of the development tools, remove unused code/data, etc. This may be similar like doing heap dumps, but with added optimization phases.
And ruricolist has written (and maintained/forked) some nice libraries. In particular his FXML is the modern successor to cxml and plays nice with xpath, etc...
https://github.com/clojure/clojure/blob/89fc0caa43811c7dfcb4...
Is this an implementation detail or a common lisp idiom to work with case (in)sensitivity?
Im interested to see how well this will fare. Personally, Im a little depressed that Clojure-in-Clojure has been postponed for nearly a decade. It would have made changing compiler targets much easier.