Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Clojure is a trinity of language, REPL, and structural editor (jakubholy.net)
99 points by lispybanana on Dec 12, 2022 | hide | past | favorite | 42 comments


I preach about using the REPL non-stop to my coworkers and we don't use Clojure. The problem with REPL-driven development is that you need to invest in your setup - so you have to believe it's worth it. Not even the Clojure REPL works out of the box: you need to make sure your definitions are reload-friendly, Emacs/Calva have to be connected for you to eval stuff with commands, use comment blocks as scratchpad, etc - it's a bunch of little conventions you need to buy into.

That being said, the setup cost is paid pretty quickly. Developers underestimate how much time they waste reloading stuff into place. Updated a function - woops, have to clear the variables I setup and run intermediate steps all over again. Even if you think 'yeah but I just write tests and those run the whole flow' using a REPL is worth it. I work with Rails, use guard and try to keep tests fast by sticking to POROs and still does not beat the interactivity of the REPL.

One workflow that comes close is working with Elm's compiler. Super friendly and interactive; gives you a similar iterative flow as a REPL but in a different context.


How is this at all different from iPython in say, a Jupyter notebook? Not only is it fully interactive but the Python system gives you rich visualization options for your data and flexibility in how you use it (e.g Colab vs local setup).


I have limited experience with Jupyter notebooks and have not tried to implement a working prototype (say, Flask+SQLAlchemy) solely using this environment.

The canonical Clojure setup would have you start a REPL when you begin your coding session (or more, could be weeks/months without a restart), edit your source files and use keybindings to evaluate text in block comments.

This basic setup can go with addons like Calva (VSCode; can inline the results, like a notebook and has other features) and Portal (can render data structures in different viz formats).

For Jupyter: - Does your source have to mimic some sort of literate programming style to keep a certain format expected by the notebook? - If you edit other notebooks, do the cells in your current notebook get updated? - Can the notebook be connected to a production environment to run code using live production data?


It is pretty similar to the Jupiter Notebook experience which is loved by many the modeller, or before that good old Excel.

Interactive development has a decent established history of lowering the bar to entry to computing.

Less familiar with Python, but my impression was that Jupyter notebooks weren't so great for nudging you towards better software engineering practices (when compared to the clojure REPL)?


Notebooks are good for exploring a problem, especially questions about data. I also don't think they are great for "software engineering", but as the name suggest, they are for notes, not applications.

When developing something closer to a program, I usually write code line by line in a text editor, but basically every line has been developed in the IPython REPL.

Sometimes I write a few cells in Jupyter Notebook to learn an API. It is really nice that you can have the output of a call in cell 1 while working on refining that call in cell 2.

Once I feel I've learned what is needed, I move the code into a .py file and turn it into a script or a module.

Despite of this workflow, I haven't found a great pairing between editor and IPython REPL and I am manually copy-pasting code between the two.

RStudio works really well in this regard, but I think that the editor runs on the same R kernel instance as the program you are developing, which makes restarting R a pain.


Not sure about the parent comment in particular, but I think the original article nails it on the head.

The 'structural editing' makes it integrate so well with the REPL. I'm not sure how Jupyter notebooks work, but in clojure every line of code you write is immediately accessible via the REPL. It would be as if python was built with the assumption that every .py file was a Jupyter notebook.

Navigating a file and want to see what some expression is? One keybinding.

Can't remember exactly how a function works and want to test it? One keybinding.

Changed some code and want to make sure the tests pass? One keybinding.

Curious what result a function will return? Well add some test code anywhere, then you guessed it, one keybinding.


It's good to see this acknowledged. I tried to learn Clojure and appreciated the language but I just couldn't get my vim head around the emacs ecosystem well enough to experience the nirvana.

I may well try again.


It's not as difficult as those who think they are elite would have you believe.

Here is my common lisp setup easily adaptable to clojure: https://blog.djha.skin/p/developing-common-lisp-using-gnu-sc...

My thoughts on emacs versus vim and a better approach to trying to get them to be useful for things like common Lisp and Clojure: https://blog.djha.skin/p/emacs-users-im-okay-i-promise/

The main idea is that you don't need an IDE. Most Ides just copy and paste stuff for you into the repl, believing that you're too stupid to learn the commands inside the repl yourself and so they'll do it for you and you'll just learn a bunch of hotkeys. As if learning the hotkeys was easier than just learning the commands. I don't mean to offend anybody but this never made sense to me. Just learn the commands, then you can use the commands from whatever editor you want without having to relearn a bunch of hotkeys switching from emacs to vs code.

Being a VIM person, I imagine you're pretty comfortable in the terminal and so will not have a problem just using the repl in one window with vim in the other. Then I just have a few plugins to make it easier to copy and paste between vim and the repl.

I will say this, getting an LSP client for Clojure does help, but between that and syntax highlighting I'd say you're good to go.


Give a try to this setup: https://github.com/rafaeldelboni/nvim-fennel-lsp-conjure-as-...

It's for neovim, but is using very modern tools and even uses a clojure like lisp to configure the setup.


I will, thanks!


I haven't used vim in years but there's a package by Tim Pope: https://github.com/tpope/vim-fireplace

This is a key piece of the REPL workflow: you rarely type into the REPL, you use commands in your editor to select code and run it in a REPL. The idea is that you eval stuff in the same place you type, and that gets run in the same environment over and over again without having to restart it or redefine the data you're using to iterate your functions.


I'm a vim head too and tried to embrace emacs, because it seems the de facto standard, but I eventually realized it was dumb to trade my editor of choice for that reason, especially at the same time I'm learning a new language. So I ventured into Fireplace and the paredit equivalent (It's been a while so I forget the name) and I was much more comfortable with that setup. Also, I'm equally as comfortable in "standard" editors, like VS Code, since I have to use Visual Studio for work most of the time (vim plugins are ok, I just don't mind context switching, feels like it keeps the mind sharp). I've tried Calva for Clojure dev in VS Code and I think it's just as nice as the other setups. I don't think anyone using an "alternative" setup is going to miss out on any of the "big ideas" that make Clojure dev so nice. I suggest sticking with vim, at least to start.

I've never had the opportunity to use Clojure in production projects but, as an exercise in learning the langue, I did a library that I've had to rewrite for many production systems (can't copy paste across companies), in various languages, over the past 15 years, and I liked the end result of the Clojure version way more than any other. It was objectively shorter and easier to reason about. Even the insane, invalid XML parsing that has to be done to integrate with a third-party interface. Just hope I get to use it, in a pragmatic sense, someday.


It's absolutely NOT production ready but I once wrote a one-liner Vim macro to send clojure forms to the REPL via ncat:

https://github.com/djtango/spartan-repl

I tidied it up a little for my personal .vimrc but it works surprisingly well for how little effort it took to configure. One known issue is if the thread of execution spawns a sub thread then exits (because the ncat socket is closed)

I was surprised just how lightweight a REPL editor integration could be - simply having a Vim editing experience over a REPL is pretty incredible


I also tried to grok emacs when I started learning clojure. Returning to (neo)vim was one of the best days in my entire career.

I now use clojure + neovim thanks to: https://github.com/Olical/conjure

Dead simple to set up and to use!


The vim/evil-equipped distributions go a long way toward helping with this.


> One workflow that comes close is working with Elm's compiler.

Another one is Ruby + Pry. It's magical.


can you send code to pry from your editor? i looked it up but never found anything. i actually took a shot at implementing an nREPL server for ruby but all the editors make too many clojure assumptions.


> can you send code to pry from your editor?

Honestly, I never really tried, and it's been quite a while since I last touched ruby. Being able to interact with a live system at a breakpoint was amazing enough to me at the time. The REPL was pretty nice from what I recall - much friendlier than irb or the builtin python one.


Yes, it's possible with inf-ruby-mode in Emacs; C-x C-e at the end of a definition works the way it does for Clojure, though the actual REPL implementation in Emacs never feels seamless the way CIDER does (i.e. it generally requires fiddling around with various config settings whereas CIDER basically Just Works™; it feels more like GUD than a proper REPL).


I've been trying to learn Clojure (well, actually Babashka (https://babashka.org/)) from a book, but the whole REPL thing and its workflow benefits didn't really convey well from such a media. It wasn't until I saw a real workflow example (https://www.youtube.com/watch?v=jm0RXmyjRJ8), that I grokked what REPL development brings to the game. It's quite possible I haven't unlocked its full potential, but I do see value in this way of working.

I'm using Calva + vscode and the onboarding seemed pretty simple. Installed Babashka using linuxbrew, then installed Calva in VScode and ran its tutorial. Calva has a pretty good guide on the structural code editing: https://calva.io/paredit/

Now I "just" need to figure out how to parse xml. Zippers melt my brain


Tried it, liked the language but hated the setup. You have to be a hardcore fan to run with CJ and present it at work for others to consider. So...apart from hobby projects, my 2c, "ain't nobody got time for that". I wish it had a better ecosystem and tooling though since I'm 99% sure this language crawls due to it drowning at the vim level still.


I thought that until I found Cursive which is a Clojure plugin for IntelliJ. I used IntelliJ for Ruby and Java for years. It's extremely good and probably much more familiar than something like Emacs if your background is with a GUI editor.


I think the setup fiddling is similar in a case where you're coming to a Java shop / project vs coming to a Clojure shop / project. It's not as frictionless as eg Ruby or Python but it's still pretty straightforward.


Clojure has so much boilerplate to get started though. It is a shame that it requires so many incantations when it makes fun of Java's verbosity.

I have moved to Common Lisp and it is much simpler and saner, while having the same REPL driven development.


Saying that CL is simpler and saner than Clojure is a pretty hot take. CL is a huge and complex language with lots of legacy decisions and quirks. Clojure is a far smaller and more focused language by comparison. Meanwhile, things like data structure literals and destructuring remove a ton of boilerplate present in CL.


What boilerplate does it need? If nothing else, for CL you need to get quicklisp seperately, while deps.edn handles that for you. I love CL, and going from automatically debugging in the repl to what are perhaps the worst stack traces I have ever seen wasn't great, but I'm seeing a lot of people mention a difficult setup I saw no trace of.


What would you suggest for someone who wanted to get started with CL? Emacs and SLIME?

(It would be nice to tinker.)


https://marketplace.visualstudio.com/items?itemName=qingpeng...

Is great for vs code but emacs and slime works of course.


The parinfer argument is funny. It's quite literally an argument for syntactically significant whitespace. With parinfer you can just remove the parenthesis in most cases! Or rather, parinfer will infer them. So.. if a computer can infer them always... why do you have them?


[deleted]


This is a great summary of what makes Clojure-the-language awesome to work with.

The REPL is way too complicated as a selling point, but it's THE concept I took from Clojure and ported it to my workflow in other languages. It has made me appreciate Hot Reloading in front end apps (and make sure it always works perfectly), make my Ruby console reload friendly, organize my React apps so business logic stays in models I can use in a REPL.


[flagged]


Clojure is an extremely fine piece of engineering, and was quite a breath of fresh air at the time of its introduction. It allows you to run stuff on the JavaVM, which was everywhere back then (still is, actually), and in the browser via JavaScript. Hickey made it happen out of thin air. That's why I take him seriously.

By the way, "complect" is an actual word.


Please don't cross into personal attack.

https://news.ycombinator.com/newsguidelines.html


Bruh... Rich Hickey is straight up a brilliant guy. Clojure is a brilliant language.

You are getting hung up on little details that are going to derail your life experience. Instead of focusing on these things that are unfamiliar to you and attacking them, why not pause and consider that there might be some real value here you haven't been able to recognize yet?


From my memory of the popular talk in which he used “complecting”, he was quite open about how silly it is or might seem as a word.


Is that the one where he showed the audience how he used to write Java (with static classes everywhere), and you realised... oh shit, this guy did not understand how to write Java at all?


Clojure runs atop the JVM. The magnificence of full interop and STM (software transactional memory) suggests a certain level of mastery of the Java language.


I love Clojure, but the Java source is oddly formatted which I never understood: https://github.com/clojure/clojure/blob/527b330045ef35b47a96...


He understood how to write Java, and attempted to do functional programming in Java, knowing full well that it wasn’t idiomatic.


"a Californian accent"

FWIW, Hickey has hardcore east coast accent, sounds nothing like any Californian who hadn't recently moved from New York or Massachusetts.


He jokes about how his formula for talks is just look up a word in the dictionary and "you're done". For example, the word "Complect" (which even my spell correct engine thinks is wrong) https://www.merriam-webster.com/dictionary/complect


So I’m just going to throw this out there … words are deeper than dictionaries. Especially in intellectual conversations concerning abstract or complex concepts, the synthesis of “new” words is pretty fundamental. The line between sentence and word in terms of the composition of elements into new combinations is less clear than a basic language understanding indicates. I call this excessively constrictive lexicality, for want of a better word.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: