7 ms·
Is there a good argument against Clojure in this case? My impression is that it's a good lisp and you can get actual work done in it which is an advantage over
by st1x7 6y ago
Is there a good argument against Clojure in this case? My impression is that it's a good lisp and you can get actual work done in it which is an advantage over some of the other options.
- phoe-krk 6y agoOne argument I can think of is that if your problem is not shaped in a functional way, then a functional programming language might be a poor fit for the job. Common Lisp is multi-paradigm language that is pretty bendy with regard to absorbing new ways of doing programming. It gets actual work done as well.
- firepoet 6y agoHow is it that you think Clojure has trouble doing things in a non-functional way? I'm just curious, as I work in Clojure primarily and may have a huge blind spot I'd love to clear out!
- phoe-krk 6y agoI don't have much of experience with Clojure myself - the above might be my first impressions from the little bit where I've tried it. Well, let me try to fix them then, and ask some questions. In Clojure, how do you usually approach problems that are shaped in an object-oriented way? In object-oriented languages, this usually includes either some sort of method calls (and therefore mutable state) or message passing (which usually involves actors, like Erlang processes). Passing all state around as function arguments is one way, but it becomes somewhat tedious as state grows large.
- shock 6y agohttps://wiki.c2.com/?ClosuresAndObjectsAreEquivalent https://wiki.c2.com/?ClosuresAndObjectsAreEquivalent
- phoe-krk 6y agoI'm aware of this. How do you achieve setters if the state you close over is immutable? Isn't that the default in Clojure, since it seems to aim for immutability by default?
- harperlee 6y agoThrough an atom (https://clojuredocs.org/clojure.core/atom https://clojuredocs.org/clojure.core/atom). The idea of accesing a closure that is mutable is as follows: (let [temp (atom 0)] (defn getter [] @temp) (defn setter [val] (reset! temp val))) To implement an object, you would do something more like: (defn new-object [init-val] (let [temp (atom init-val)] {:getter (fn [] @temp) :setter (fn [val] (reset! temp val))})) (def obj (new-object 0)) ((:setter obj) 12) To define interfaces, you could check whether the map/object conforms to a spec, etc. But obviously all this is not very idiomatic; in clojure you would keep those functions first-class through defn instead of tying them to the object / map, and would pass state as an argument. Something like: (defn getter [obj] @obj) (defn setter [obj val] (reset! obj val)) (def obj (atom 0)) ; This gives you the ability (and need) ; to explicitly track the list of ; existing objects in use lest they are garbage collected. (setter obj 12) If obj has structure (e.g. it is a map such as {:type :my.personal/type :val 12}) you can identify its type through the type keyval and can check conformance to a spec, etc. As it was said in the previous post, it's equivalent. It's a matter of how to organize code.
- phoe-krk 6y agoThat's a good explanation. Thanks!
- richeyryan 6y agoYou could have an atom that holds the state and a function which can update that atom. You might do something like the elm architecture where you pass a message to a reducer which produces the new state that the atom is set to. All the logic is contained in the reducer and is pure and immutable and the state change happens at a single controlled point.
- marcofiset 6y agoWhat would be an example of "problems that are shaped in an object-oriented way"? That just doesn't sound like a thing to me. That may originate from a bias you may have from developing primarily in OO languages. Clojure does have constructs to manage state. You don't need to shove it all into your function arguments.
- phoe-krk 6y agoSorry for the mind shortcut. By that, I meant all sorts of problems where multiple state-bearing entities communicate via message passing - usually implemented via method calls in OO languages.
- chris_j 6y agoWell Clojure most definitely does support state-bearing entities that communicate using message passing (channels / agents / atoms...) and, while I confess I that I personally don't use them in _quite_ the same way that I use objects and method calls in an OO language, I find that programming in OO and functional languages is kind of converging towards the same point: functional programming in the small (immutable value objects that are worked on using pure functions) and OO in the large (state-bearing entities communicating using message passing).
- LeonidasXIV 6y agoFor starters you'd need to have imperative control structures like `while`, `continue`, `break` and a `return` that basically returns from anywhere. That can probably be built with macros. Then you would need to have ways to mutate variables, so you'd need to stop using Clojure's persistent collections and instead use the ones provided by the JVM. Overall, you can do it if you want to, it is just somewhat painful to do so and the language will fight you. This is like my who tried to write functional Python which is possible but then it is just a much worse Clojure.
- firepoet 6y agoHow is the VSCode support? I've only used IntelliJ + Cursive for Clojure and am quite spoiled. That's the only reason I might not recommend Clojure for a VSCode user. Now, if said user is interested in switching to Emacs or IntelliJ, I'd think it would be a perfect fit.
- st1x7 6y agoI think it makes more sense to pick the language first and then find an IDE for it that you like instead of the other way around.
- farias0 6y agoAs a Lisp and Clojure beginner, ehhhh. I could get work done, but I depended on the terminal for REPL and compiling & running. I ended up using Emacs, which along with .NET were the only cases where VSCode didn't feel ideal for me.
- tribaal 6y agoChiming in since I'm a bit disappointed with Clojure VS Code support:calva (the clojure extension) works great, unless you also want vim bindings. In which case it's a bit of a cluster. It's documented and I understand why - but it's still a pain point (it makes the escape key not exit insert mode anymore, by default). (nota bene: I understand these things are hard to solve and I don't mean to throw the stone without putting my own time on the line to fix it, but that's one reason I'm not using VS code for clojure. Doom emacs with cider is still better, even if not perfect). If people know of someone I could throw money at to solve the integration for VS code, I'd be happy to do that. If you find a good/great experience for clojure with vim keybindings, I'm all ears.
- Zelphyr 6y agoVim with the Vim-Fireplace plugin works great for me.
- ptttr 6y agoNowadays, you can get VSCode support for Clojure pretty much out of the box with calva[1] extension working together with clj-kondo [2] almost without any configuration. It works great - I've switched over from Cursive and I'm not looking back. [1] https://calva.io/ https://calva.io/ [2] https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#clj-kondo-extension https://github.com/borkdude/clj-kondo/blob/master/doc/editor...
- simongray 6y agoThe main issue with Clojure is probably its tight integration with the various host platforms. When you get a stack trace in Clojure/ClojureScript, you basically get a Java or JavaScript stack trace, so there is some expectation of familiarity with the host platform. If you already have some experience with the host, then this shouldn't be a big issue, but it's a dealbreaker for some people. Another issue has to do with startup time. The Clojure application bootstrap process is relatively slow, i.e. start-up might take 1 second, so it's great for server applications, but less great for Android apps or other CLI scripts that expect require instant startup. It has been approached in different ways, e.g. compiling Clojure with Graalvm native image or using ClojureScript instead of JVM Clojure. The latest solution is Babashka which provides a variant of Clojure specifically for writing CLI scripts. Otherwise, Clojure is an excellent language which both modernises Lisp syntax significantly and implements a very well thought out standard library for doing functional programming. There are many great features, but the standout ones are probably the persistent data structures (which syntactically act both as data structures and functions) and parallelism/concurrency support. It's also very natural to do interop with the host platforms (Java, JS, .NET) and the data-oriented style of programming makes communication between backend (Clojure) and frontend (ClojureScript) extremely simple. So it's pretty much the perfect full-stack language for information systems. I would take a look at the rationale: https://clojure.org/about/rationale https://clojure.org/about/rationale
- flavio81 6y ago>Otherwise, Clojure is an excellent language which both modernises Lisp syntax significantly and implements a very well thought out standard library for doing functional programming. There are many great features, but the standout ones are probably the persistent data structures (which syntactically act both as data structures and functions) and parallelism/concurrency support. It's also very natural to do interop with the host platforms (Java Absolutely everything mentioned above in this quote is available in Common Lisp as well by just loading the needed libraries. >Another issue has to do with startup time. The Clojure application bootstrap process is relatively slow, i.e. start-up might take 1 second, >The main issue with Clojure is probably its tight integration with the various host platforms. When you get a stack trace in Clojure/ClojureScript, you basically get a Java or JavaScript stack trace, so there is some expectation of familiarity with the host platform. Correct. And there are no such problems in Common Lisp. Except if you want to execute CL in a JVM, in which case the available implementation, ABCL, does take a slow time to start. Otherwise it's a great implementation.
- vindarel 6y agoI tried Clojure a bit and, compared to CL, I find it bloated :S Installing a library takes ages, a lot of memory, and I can't do it from the REPL (so I must quit my development environment, and start it again). CL feels very snappy. I can even install a new library to a running web app. I know it's dangerous, but it works and it helped me already :)
- dustingetz 6y agoyes but clojure can get you a job
- vindarel 6y agoProbably more than CL yes, but thank you I create my own job.
- slifin 6y agoLibraries can be installed from the REPL in Clojure but it does require a dependency ahead of time: https://insideclojure.org/2018/05/04/add-lib/ https://insideclojure.org/2018/05/04/add-lib/ Some of Clojure's other runtimes perform a bit better, Babashka, CLJS, CLR, GraalVM for different trade offs if you need something like a scripting language or native images etc I'm sure CL is still quicker but there are options
- harperlee 6y agoNote that this needs to be required because add-lib is still alpha, but it is to be expected that once it is in the main deps functionality, it will come out of the box!
- flavio81 6y ago>Is there a good argument against Clojure in this case? I use Common Lisp and my main argument will be that Clojure isn't an "interactive programming" language like Common Lisp, Smalltalk (and Pharo, Squeak, Scratch) are. And, for me, this is removing one of the main, core advantages of Lisp. Dispensing with the interactive programming features is, IMO, a step backwards in the state-of-the-art. Common Lisp ADDED all the improvements in the state of the art: Interactive programming from Smalltalk, lexical scoping from Scheme, various high performance/low level features from StarLisp and ZetaLisp, a very powerful OOP system, etc. And then, thanks to it being highly extensive, almost any feature can be added to it. Clojure features like threading macros, immutable seqences, software transactional memory, and others, are already available in Common Lisp by just importing (loading) the respective library. One of Clojure's main advantage is to be able to call Java libraries. But, surprise, you can do this in Common Lisp too, easily, by using the Armed Bear Common Lisp (ABCL) implementation. Which runs on the JVM too and makes the process of calling Java libs really, really easy. I have made a working example here, calling all the Swing UI library (java) from lisp: https://github.com/defunkydrummer/abcl-jazz https://github.com/defunkydrummer/abcl-jazz It's true that Clojure has more widespread adoption in the industry and more libraries. However the library ecosystem on Common Lisp is decent. >and you can get actual work done in it which is an advantage over some of the other options This implies you can't do "actual work" in, for example, Common lisp. Which is not true, since there are companies that, in this very moment, are doing well paid, critical commercial work using Common Lisp.
- chris_j 6y agoWhat does Common Lisp have, in terms of interactive programming features, that Clojure (together with Cider and nrepl etc) lacks?
- flavio81 6y agoSee my reply above: https://news.ycombinator.com/item?id=25451321 https://news.ycombinator.com/item?id=25451321
- phyrex 6y agoI've been programming Clojure for a while and I've dabbled in CL, and while the CL debugger is certainly nicer, I don't see a major difference in how you develop interactively. Could you explain where do you see Clojure falling short?