Hacker News new | ask | show | jobs
by yogthos 3235 days ago
One huge difference is the workflow you have in Clojure. REPL driven development is an experience unique to Lisps. When you're working with Clojure, any code can be run in the context of the live app straight from the editor as you write it. This is an amazing experience and very mind expanding in what a development process can look like.

Also, anybody who wants to try FP style programming, but isn't interested in static typing is much better off with Clojure. Type systems in languages like Haskell and Idris add a lot of complexity and mental overhead that's not present in a dynamic language.

3 comments

I don't think that's entirely unique to Lisps, you can get a REPL into an existing Erlang instance very easily. More easily than getting nREPL running in Clojure, actually. I believe Smalltalk as well, although I'm less confident on that one as I haven't used it much.
As someone who's professionally developed mostly in Erlang and Clojure in the last 6 years, it's not even close. I love Erlang, but the REPL is severely underpowered and used mostly for debugging and inspection.
The difference is in the editor integration. When you work with Lisp, your editor is connected to the running instance of the application. You have shortcuts to reload any symbol in the application at runtime directly from the editor.
I work in Scala and it has live code update, interactive worksheets and a repl.

As for type systems increasing complexity I think that depends on the application. As a beginner to Clojure I would pass unstructured data around all over the place and then have the mental overhead of trying to remember the structure or fix it all at runtime.

The biggest difference is the editor integration. Scala, like most languages has a REPL that's basically a toy you use on the side. Clojure REPL is tightly integrated into your workflow.

I did a talk last year where I illustrate it starting around 15 minute mark https://www.youtube.com/watch?v=nItR5rwP4mY

I'm not aware of any non-Lisp languages that provide anything close to that.

The REPL driven workflow directly addresses the problem you're describing as well. When I'm working with Clojure, I never write a lot of code before running it. Each time I write a function, I run it and see exactly what it's doing. This means that I never have to keep a lot of context in my head.

Let's say I need to pull some data from the database, massage it, and return it to the client. I would write the function to read the data, run it to see what shape of the data I get. Then, I would write the function that consumes that data and transforms it. Again, I'd run it and see that I have the data I want, and so on. At each step of the process I only need to consider the last step and the next.

Also, Spec and Schema are commonly used in libraries to provide the description of the data at the API level. This is where I really care what the shape of the data is, as opposed to typing every single function I write.

Nice talk. I agree with you that the repl in Clojure and Common Lisp etc is much more of a first class citizen in the development environment. What people often don't realize is how powerful the repl and worksheet can be in scala development.
Thanks, having editor integration with the application runtime completely changed my workflow. I simply couldn't go back now, having instant feedback on the code you write is extremely satisfying.

What surprises me is that none of mainstream languages provide this kind of environment. Lisp and Smalltalk have been around for many decades, and somehow this workflow ended up being completely neglected in the mainstream.

This is what clojure.spec is meant to address. It's helped me, but I am actually trying to get some momentum in Haskell now... I have a saying, "Constraints free the mind." Frameworks, Type systems, etc., provide the constraints we need to let our mind think about the actual problem instead of suffering from analysis paralysis.
Is there something about clj's repl that makes it any different from ghci's?
As an Emacs user, from my experience the Clojure REPL has much better integration with my editor than any non-LISP I've used, which includes Haskell and Erlang. Most of the time I'm not typing commands into the REPL - instead, I'm evaluating code inline, which means I don't need to jump back and forth from the source file to the REPL. It's a much more interactive and productive experience for me, and I haven't been able to fully replicate anywhere else - though it's possible I haven't discovered the right tools for those other languages yet.

I use CIDER with Emacs for Clojure integration: https://github.com/clojure-emacs/cider

When the experience is amplified by homoiconic data structures and structural editing, yes -- exploratory, ephemeral metaprogramming is a breeze. Compound Clojure data literals have a fully readable print representation that can be generically manipulated by built-in core library functions. Say I have a DSL that takes a bunch of nested maps and vectors as an input spec and compiles them to nested closures, and I want to create a large spec derived from some other source satisfying certain constraints, but it's not worth defining yet a higher-level DSL for a one-off definition that I intend to commit to source control. I can generate that data structure any way I like and spit the result out at the REPL or in an interactive buffer, then effortlessly plop that structure or any of its substructures into an EDN file or just inside a `def` or `let` binding in a regular Clojure file, which I then pass to the DSL compiler. It's much simpler than manipulating things like GADTs in Haskell. Even in Common Lisp, it might require some ad-hoc parsing code to accomplish the same thing.
Yes, you can reload any symbol in the CLJ REPL directly from the editor. You can also evaluate any function within the context of the running application without going through the main. The REPL is an integral part of the development process in Clojure. You can see this in action here around 15 minute mark https://www.youtube.com/watch?v=nItR5rwP4mY
R and RStudio are actually quite good in this aspect.

- You can evaluate any part of editor in console with keyboard shortcut. The only difference between using console and editor is that your input is easily saved in editor.

- The environment browser make inspecting variables, data structures much easier.

Besides, in R you want to use vectorized functions for better performance, so you search for general functions and combine them, which actually promote good functional programming style instead of a big control block with many processes intertwined.