5 ms·
Don't really get the criticism of Clojure for being hosted on the JVM, particularly relative to its status as a "productive" Lisp. Like oh, you get access to on
by charlotte-fyi 3y ago
Don't really get the criticism of Clojure for being hosted on the JVM, particularly relative to its status as a "productive" Lisp. Like oh, you get access to one of the biggest and most mature library ecosystems out there as well as best in class operational tooling? Obviously there are use cases where the JVM doesn't fit and all things being equal I prefer shipping statically linked binaries too, but the JVM still feels like an obvious "pro" here.
- askonomm 3y agoAnd quite a lot of people actually do ship statically linked binaries with Clojure, using GraalVM. Clojure LSP server for example is distributed as a static binary.
- colingw 3y agoYes, although that solution can't yet be said to be "push button". My impression is that there are a decent amount of people who want non-JVM, native Clojure. Hence efforts like Janet and Jank.
- ska 3y agoI think hosted is almost tautologically a mixed bag - you get access to the host (both +ves and -ves) but you also introduce a layer and some invariable friction.
- whateveracct 3y agoThe JVM precludes general tail-call elimination though.
- thmorriss 3y agothe clojure loop construct is often cleaner than code written to be tail recursive
- uyrifo 3y agoAnd often faster: https://medium.com/hackernoon/faster-clojure-reduce-57a104448ea4 https://medium.com/hackernoon/faster-clojure-reduce-57a10444... Yet it’s always noted as code smell associated with “inexperienced candidates” in interviews. For that matter, first and last too: https://medium.com/hackernoon/faster-clojure-reduce-57a104448ea4 https://medium.com/hackernoon/faster-clojure-reduce-57a10444... The amount of paired programmers suggesting changing nths to firsts and lasts is demoralizing.
- jordibc 3y agoIt does preclude it, but clojure found an arguably elegant solution to it, using recur[1] instead. As a plus, in addition to achieving the same result as tail-call elimination, it does check that the call is indeed in tail position, and also works together with loop[2]. For me, it made me not miss tail-call elimination at all. [1] https://clojuredocs.org/clojure.core/recur https://clojuredocs.org/clojure.core/recur [2] https://clojuredocs.org/clojure.core/loop https://clojuredocs.org/clojure.core/loop
- packetlost 3y agoIt is, IMO, a missed opportunity to use a hard-coded identifier for `recur`ing instead of the `(let sym ((...)) ...)` form that would let you nest loops. Aside from that, I agree. Tail-call optimization's benefits are wildly overblown.
- whateveracct 3y agoThe benefits aren't overblown if you are someone who learned Lisp with a functional approach. As in, using higher-order functions etc. You have to be careful whenever you approach a problem that way on the JVM.
- packetlost 3y agoCan you provide an example?
- whateveracct 3y agohttps://news.ycombinator.com/item?id=39261659 https://news.ycombinator.com/item?id=39261659
- xdavidliu 3y agowhat does tail-call optimization have to do with higher-order functions? I thought the former pertains to iterative procedures written with recursive syntax, where the recursive call is at the very end of the function and called by itself, so stack size is O(1). Higher-order functions means passing functions to things like map, filter, etc.
- LispSporks22 3y agoI know of one company that dumped its clojure code base because lambda costs were too high. They even experimented with graal as a fix.
- whalesalad 3y agoI would have dumped lambda as a runtime before dumping the codebase. Obviously we don't know the full story but that sounds a lil silly to me. Plus lambda's will stay alive for quite a while if they are in use. So startup time is felt once, but then would be identical to any other language or runtime.
- MathMonkeyMan 3y agoI hardly wrote any Clojure, but the only thing that bugged me was the startup time of the repl. It's been talked about enough. Yes, that problem goes away if I use a proper setup with a language server or whatever, and yes it doesn't matter for "situated" production applications, but it still peeved me. What do I care if it's in the JVM? Sure, a JVM instance uses a lot of memory to help the garbage collector, but that doesn't bother me. JVM is just an old, mature ecosystem. Every runtime we work with (browser, nodejs, CPython, your decades of hand-written C++, the Go standard library) shares design tradeoffs with the JVM. Nothing inherently off-putting about it.
- coffeemug 3y agoI haven’t touched JVM in ages, but there are two things off putting about it. First it’s viscerally slow. They have a state of the art GC, amazing benchmarks, tons of work going into performance, but it still feels slow and laggy when you develop on it. None of the other ecosystems you mentioned have that problem (including Python). Second, they have a bad sense of design. The class library comes from a culture of needing three classes to open a file, and that culture permeated through the entire ecosystem. Almost all the software in it feels bloated and over engineered. The modal JVM experience is spending 95% of your time dealing with “enterprise-y” boilerplate that turns out to have nothing to do with the enterprise and everything to do with bad design decisions and the culture downstream from those. C++ has its own flavor of this problem, but certainly not Python or Go.
- 7thaccount 3y agoI couldn't agree more. I'm not very knowledgeable on Java, but was blown away every time I looked to see the crazy amount of boilerplate to do anything. There are all these design patterns that seem to only exist because the language is so terrible. Thousands of people who aren't professional developers write millions of lines of Python each year (just a guess, but sounds right) and the vast majority just write code and don't need 50 classes in their application to do something.
- 3y ago
- outworlder 3y ago> Don't really get the criticism of Clojure for being hosted on the JVM, particularly relative to its status as a "productive" Lisp. If you are doing long running server side apps, it is a better fit. Even better if you are already a Java shop. Otherwise, its either detrimental or, at the very least, a source of very 'alien' behavior, not the least of which being the stack traces. That gets pretty obvious when you compare with the likes of Common Lisp with its incredibly elegant system that's essentially Lisp _almost_ all the way down. The JVM has its own advantages of course. Billions of dollars of optimization work being one of them. Being able to use java libraries to fill the gaps (at the expense of the less elegant stack traces and some It can be a complete show stopper in many applications. Say, you want to interface with C libraries. Or embed some form of Lisp in your app. Browser-based apps (emscripten doesn't help you), which is why Clojurescript exists. Or you are building something like an iOS application. I have successfully embedded (although not shipped to the App store) Chicken Scheme in a couple of different ways. The first, as a library with all the cross compilation nonsense. And the second, by simply telling the compiler to stop at C code generation, adding the C blob in the app, and compiling everything together with the rest of the app. That gave me a remote REPL which was amazing for debugging.
- roenxi 3y agoFair points, I say. But interfacing with C isn't a show stopper is it? Clojure can bridge to C by exposing the C library though the JNI/JNA framework. It isn't much fun and there are certainly situations where I'd say Clojure was a poor choice for calling C/C++ libraries, but if you need to do it then it can be done.
- truculent 3y agoIt also gives you access to Babashka if you want Clojure for other use-cases where start-up time is an issue https://babashka.org/ https://babashka.org/