5 ms·
I always think it's hilarious when Clojure enthusiasts try to address concerns about the language by talking about parentheses, as if that was actually the majo
by darksaints 6y ago
I always think it's hilarious when Clojure enthusiasts try to address concerns about the language by talking about parentheses, as if that was actually the major barrier to entry. The parentheses are at best a mild inconvenience...many people love them, including myself, but few people cite the parentheses as a reason to not use the language after actually trying it out. A non-exhaustive list on why not clojure:
* It's slow
* Development with the REPL is slow because the startup times are glacial and REPL-oriented development usually requires tons of from-scratch restarts.
* The tooling sucks: build systems, IDEs, debuggers, etc. If you feel like writing code with just an editor and a terminal is like going back to the stone ages, you're gonna want to bash your own head in with a mammoth bone club.
* Java interop is a black art, and when you need to use it, it will ruin any sense of elegance you felt for your code originally.
* The ecosystem practically doesn't exist, unless you're willing to absorb a lot of java libraries. See above.
* The lack of static types hurts you in many ways, most of all your ability to refactor with confidence.
* Clojurescript isn't the same language, no matter what they promise you. Clojurescript is weakly typed, Clojure is strongly typed. If you aren't aware of the difference, prepare to spend weeks of your life tracking down bugs that would only be days in Clojure, and would never exist in the first place in a statically/strongly typed language.
- raspasov 6y ago* It's fast enough for 99% of apps out of the box. It's fast enough for 99.99% of the apps with minimal tuning. * Yes, if your project is very big and macro heavy, it can take some time, but startup times have improved. In any case, I BARELY need to restart my development JVM. I have one currently running that I haven't restarted for 1 week+. * Depending on what's your cup of tea, there's emacs/CIDER or IntelliJ/Cursive. They both work well. IntelliJ/Cursive is an excellent IDE combination. I use it every day. * Java interop is very straightforward, not sure what you mean. Sure your code might not be all pure anymore, but that's the price for solving actual problems. * Good java libraries have wrappers. A ton of original Clojure libraries as well. https://github.com/cgrand/xforms https://github.com/cgrand/xforms for example allows you to easily do things that I can't even imagine doing in an imperative language. * Static vs dynamic typing: don't want to get into that. * "Clojurescript isn't the same language". I use both Clojure and ClojureScript every day and as far as Clojure-only code is concerned, it works in both languages 99.99% of the time. One case you can encounter issues is if you do something host-specific, like dealing with numbers. That's by design. Clojure embraces each host, does not try to reinvent it. When you just use pure Clojure data structure manipulation, it works the same across both languages and works like magic.
- mbrodersen 6y ago> It's fast enough for 99% of apps out of the box. It's fast enough for 99.99% of the apps with minimal tuning. It might be true that Clojure is fast enough for the apps you write. I know it is not true for the apps I write and have worked on in my professional career.
- raspasov 6y agoIs Java fast enough for the apps you write? What kind of apps do you write?
- darksaints 6y agoFrom a performance perspective, Clojure isn't even close to Java. Although it's probably not worse than Python or Ruby. There are millions of apps out there that are performance sensitive enough to not use Python or Ruby, but not so performance sensitive that they couldn't use Java. https://www.diva-portal.org/smash/get/diva2:1424342/FULLTEXT01.pdf https://www.diva-portal.org/smash/get/diva2:1424342/FULLTEXT...
- 0xc0171 6y agoWow, performance comparison by someone writing Clojure for the first time, wonder how that will go. Here's what someone with more than superficial understanding of the language can produce. Try not to base your argument on the first google search result next time https://github.com/joinr/performancepaper https://github.com/joinr/performancepaper
- kolme 6y agoI'm going to have to disagree with almost everything you said, let's have a look: > I always think it's hilarious when Clojure enthusiasts try to address concerns about the language by talking about parentheses, as if that was actually the major barrier to entry. Not that they are a major barrier, but they do scare people away. I know this because I've been tempted to try lisps before and after having a look at some source code, I was "scared" of the parenthesis. They are ugly (at least I thought at first sight) and they seem like very tedious to type. Of course I know better now, but that was _the_ reason I had not to try lispy things, at least on a couple of occasions. So yes, the "the parens are A-OK!" is absolutely warranted when trying to sell Clojure or any lisp for that matter. > It's slow So what? If I'm not writing anything CPU bound, I'm not very concerned about that. Clojure is fast enough for most things. The performance penalty is completely justified if it takes me half the time to write an app. This is just a trade off, or do you write all your stuff in ASM? > Development with the REPL is slow because the startup times are glacial and REPL-oriented development usually requires tons of from-scratch restarts. This is just very much not true. First of all, nobody is forcing you REPL-oriented programming. Second of all, it doesn't take more than a couple of seconds for most apps to restart. And third, if you use "def" and "defonce" correctly you'll hardly ever have to restart the REPL. > The tooling sucks. That's just your opinion, man, and it's also pretty rude. Clojure have awesome IDEs and tooling, and the aforementioned REPL-development allows you to have the same "react-hot-relading" developer experience, anywhere. > Java interop is a black art. Java (and Javascript) interop is pretty straight forward. You call functions and instantiate classes and stuff. No naked dancing under the moon involved. > The ecosystem practically doesn't exist. It maybe didn't some time ago. The ecosystem right now is thriving with pretty cool projects. > The lack of static types hurts you in many ways, most of all your ability to refactor with confidence. That's also pretty subjective, in my opinion the only thing that gives you confidence to refactor is unit testing. Plus there's other ways to validate parameter and return values in Clojure, and they are not limited to the type. You'll agree, that a return value is of a given type doesn't guarantee that it's correct. > Clojurescript is weakly typed, Clojure is strongly typed. Plain wrong, types are semantically equal in both languages (they are weak). The semantics of the target languages are just implementation details. You can try this on a REPL of any variant you like: (def foo 42) (def foo "Hello, World!") Sharing code between Clojure and Clojurescript is fine, especially if you stick to the built-in data types and functions. Of course if you have a lot of specific interops interleaved, it's going to be painful.
- dimitar 6y agoWhile everyone is entitled to their own opinion, I think it is worthwhile to give more detailed examples - like for example slow compared to what? For example there is a nice discussion over slow startup (note that for the most people the impression that it is slow comes from the Leiningen startup which starts two JVM processes): https://stuartsierra.com/2019/12/21/clojure-start-time-in-2019 https://stuartsierra.com/2019/12/21/clojure-start-time-in-20...
- darksaints 6y agoOkay, here is an example. Let's say you're writing a web app, and you want to stick with the JVM. Pull up with Web App Framework Benchmarks, narrow it down to Java, Kotlin, Scala, and Clojure. Let me know when you have stopped scrolling, cause it takes a while before you see the first Clojure framework. Unfortunately, web apps are probably the thing that Clojure does best, and Clojure is already plenty slow there. Try it out for something typically throughput intensive (like mathematical programming or machine learning), or short lived (like CLI apps), and you'll give up almost immediately.
- capableweb 6y agoThere haven't really been a lot of efforts to get a high-speed web frameworks done in just Clojure as that's not normally how professional Clojure developers work and deploy code. Not a lot of Clojure developers use frameworks in the first place, so the HTTP server ends up being something that gets pulled in as a library, and since it's running on the JVM, you use JVM servers, which are fast. vertx seems to be something that scores high, but unfortunately only the Scala binding seems to be in the benchmark you mentioned. Here's a Clojure alternative: https://github.com/vertx-clojure/vertx https://github.com/vertx-clojure/vertx CLI apps are easily solved with Babashka now.
- fulafel 6y agohttps://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=json https://www.techempower.com/benchmarks/#section=data-r19&hw=... Clojure is on place #20 with a score of 1.3M vs 1.6M of the winner. That's fast enough. More broadly: These kinf of benchmark numbers matter in a pretty small niche of web services and it rarely makes sense to make it a big factor in PL choice.
- jgalt212 6y ago> REPL-oriented development usually requires tons of from-scratch restarts. I heard that. I've read Clojure developers keeping the same REPL running for days and avoiding this problem, but I'd always be worried about the state of the global namespace not being what I thought it was. And this is especially true during development / exploration.
- dimitar 6y agoThe only time I need to restart is when I load new libraries but you can use https://github.com/clj-commons/pomegranate https://github.com/clj-commons/pomegranate
- dgb23 6y agoClojure is fast or similar in comparison to main stream dynamic languages. REPL development is what I miss so much from other languages. You typically don’t add dependencies as frequently for startup being an issue.
- codespin 6y agoTooling, ecosystem, and Java are what killed clojure for me. I love the language and the way Rich Hickey approaches it, but I was constantly frustrated with the lack of an IDE and having to stop to deal with Java and Java tooling errors all the time. In the end I felt like Clojure was too clever for its own good. By relying on Java (which was a great choice) it took a lot of the oxygen out of the ecosystem for other devs to build tooling and libraries, and without that there aren't as many people participating or becoming a well known community member from their work there. Again, can't say this was the wrong choice, but in my opinion ecosystem is the #1 thing for a language and the way Clojure was done had an impact on how the ecosystem could grow.
- simongray 6y ago> the lack of an IDE What's wrong with Intellij with Cursive?
- EastLondonCoder 6y agoHere are my observations after doing clojure for a bit more than a year coming from doing js for two decades. It’s fast, both clj and cljs but performance is non deterministic and as with most functional languages it can be hard to reason about performance. Profiling cljs is very hard Coming from the js world I feel that tooling generally works. Especially when it comes to build systems. Very happy to not deal with webpack inconsistencies. With regards to ides there’s cursive for IntelliJ users, Calva for vscode. I can’t comment that much on Java interop. Js interop is a mild inconvenience. With regards to ecosystem, google ability is an issue but tempered by the simplicity of both clj and cljs. About types, there are a class of bugs they will help to avoid. It does help with understanding intent of the code you work with. The drawback is that they help facilitate abstraction and does not help with reasoning that much about a program actually runs. Yes cljs is a different language. But in practice it feels very much the same. I do however have a big issue with being able to push deterministic performance out of it. Keeping execution time for any frame below 16ms can be a challenge and for some type of front end stuff js is to be preferred All of these things are quite insignificant on how fast a team can churn out good quality code using clojure. I’ve never seen any team that I’m with at the moment write correct, readable and fast code as quick.
- Scarbutt 6y agoTo expand: Compared to JS, yes, it's slow. You can make Clojure run faster but you will be writing Java with parenthesis not Clojure. Startup times are indeed atrocious, in Clojure the REPL is obligatory and not optional because of this. You can avoid REPL restarts by using a third party lib like component but you have to buy into a new architecture for your program that can be overkill for many occasions. Java interop is not a black art but it is painful, the JVM has many great libs but the majority are not, many are loaded with lots of methods returning void, data models like everything needs to a be subclass of an abstract class, etc... So while you can develop with time how to write ad-how Clojure wrappers for your use case faster, you waste lots of time doing it. And yes, this something you have to continually di cause as you said, the ecosystem is very poor. Without going into the static vs dynamic typing debate, I would say Clojure is at the top of the dynamic languages spectrum (the best in its class if the JVM fits nicely the problem at hand). Clojurescript's interop with the JS ecosystem is crippled by relying on the closure compiler, which doesn't play well with anything in the JS ecosystem.
- joncampbelldev 6y agoRegarding REPL restarts: You don't need to use stuff like component. There are far lighter weight alternatives with no requirements for app structure. I use "mount" [0] for this. You define "start" and optionally "stop" code for anything in your app that you consider stateful and would like to reboot (like db conn pools, config loaded from files / env etc). No interfaces / protocols, easy app restarts within the same repl, no enforced structure in your app. You just use the resources as if they were def'd vars in a namespace (because they are). Regarding ecosystem and interop, in my experience (using clojure for about a third of the stuff at my job) I've rarely encountered a problem directly interop-ing with a java library, things like "doto" and "reify" do a good job of smoothing the rough java edges off. More importantly I've usually had the choice of either directly using the using a pure clojure alternative or direct interop with java lib or using a clojure wrapper around the java lib. Incidentally those are my preferred choices in order (assuming the features I'm interested in are supported equally). Perhaps I have been lucky in my requirements from the clojure / java ecosystems. I find the most important lesson I learned was to only use clojure wrappers if they are of a supremely high quality (either auto generated like cognitects aws lib or with a massive amount of momentum behind them like clj-http (wrapping on java http components)). An average quality or not super actively maintained wrapper is much worse than direct interop (again leaning heavily on the provided macros for interop to sand off the nastiness). [0] https://github.com/tolitius/mount https://github.com/tolitius/mount