I think you might be missing the main "aha!" of clojure REPLs vs REPLs in non-homoiconic languages: you can very easily execute small parts of the program you're editing without re-typing the code.<p>In emacs, for instance, you often use `eval-last-sexp`, by default bound to C-x C-e. This lets you move your cursor to a particular point in the file, often deep in a function, and get the results of just the form(s) you're pointing at.<p>This is a superpower! It lets you test small pieces of your code without writing any test harnesses or scaffolding. Try it with an editor that embeds the repl and has these commands, and you'll never want to develop any other way.<p>It does cause you to want to structure your code in 'repl-friendly' ways, so that you can, say, restart your main server or reset your state without restarting the whole process.
This post could be summarized as "write as much of your project's tooling as you can in the project's main programming language and the project's main programming language should be Clojure" and I agree wholeheartedly.
Thanks for introducing me to `add-lib` This is going to be a huge time saver :)
More info here: <a href="https://insideclojure.org/2018/05/04/add-lib/" rel="nofollow">https://insideclojure.org/2018/05/04/add-lib/</a><p>Hopefully there will be some way to just "reload" your whole `deps.edn` though<p>"If you get an error, the execution stops by default and you get a stack trace."<p>I'd say the other missing piece of REPL development is that while you get a stack trace, you don't get a program state like you do with GDB or ELisp. Maybe I'm "holding it wrong" but this causes a lot of friction and lost time. I'd be curious how others approach this. And that all being said, the CLI doesn't relaly offer a better alternative here.<p>For entirely replacing the CLI I think that since Clojure is a general purpose language there ends up being a tad more boiler plate than you'd like.. It's not at the point where you're gunna just run `clj`, load in some library with `add-lib` and start messing around b/c things are just a tad too clunky.<p>For instance if you wanna read in a CSV file (I had to look this up)<p><pre><code> (-> "my-csv-file.csv"
(io/file)
(.getCanonicalPath)
(io/reader)
(csv/read-csv :separator \,)
(#(into [] %)))))
</code></pre>
Uhh.. so you're prolly gunna want to wrap that up in a helper function. I personally end up making a dummy "project" where I keep a bunch of helper functions and then doing my REPL "scripting" and messing around in that. It feels a bit wrong.. but at least to me it looks like a solvable limitation. Given a nice set of helper libraries you could probably get to a point where a bare `clj` REPL would be as ergonomic as a more explicitely interactive language like R/MATLAB/etc.
> Don’t forget the set -euo pipefail at the beginning of your script. What does -euo means? I don’t know, I copy-pasted it and man set said there is no manual entry for set.<p>Use "man bash" to find the list of built-in commands. Scroll <i>way</i> down, or search for "SHELL BUILTIN COMMANDS".<p>The "e" command-line switch to the set command tells the script to exit immediately if there is a non-zero return value. The "u" switch tells the shell to treat unset variables as errors when performing parameter expansion. The "o" switch enables the following option (in this case "pipefail"). "pipefail" tells the script to return the value of the rightmost command that returned with a non-zero value in a pipeline. This is all paraphrased, the details are in the man page.
Considering its ecosystem, what do most here use Clojure for or what do you think is its sweet spot? I used it in a project with pg/ring/reitit and while some things were nicer it was not better enough to make me switch from pg/nodejs/express for new projects. Used emacs with inf-clojure (found cider too bloated and buggy, was tempted to port some features of cider to a fork of inf-clojure) and macros were helpful in a couple of places, but other than that, you can write JS almost as how most use Clojure. Also found JS to be faster unless you got out of your way to write Javaish Clojure, which reminds that is was a time sink having to deal with Java libs(it's really not as "seamless" as most advertise) because of no Clojure equivalents.
Some Clojure frameworks and libs do provide REPL support for things that we would otherwise expect to be CLIs, such as running migrations, (re-)starting services and so on.<p>The startup time criticism is valid, but in context of development you typically don’t restart it except you pull in deps (very rare) or something terrible happens (rare).<p>Then, there is also borkdude/babashka which is a Clojure powered scripting tool with fast startup times due to GraalVM.
> I use add-lib branch of tools.deps.alpha that allows me to add dependencies dynamically at the REPL and then start using them immediately, just like in the shell.<p>You could do this with (battle-tested) pomegranate [1] ages ago, which is used by leiningen as the default resolver.<p>[1] <a href="https://github.com/clj-commons/pomegranate" rel="nofollow">https://github.com/clj-commons/pomegranate</a>
Linked to in the article: UNIX as IDE (<a href="https://blog.sanctum.geek.nz/series/unix-as-ide/" rel="nofollow">https://blog.sanctum.geek.nz/series/unix-as-ide/</a>)