I just started to use Clerk, even without thinking a lot about the "output" in the browser. It is very useful to just press "Ctrl-c c" (clerk/show! ) after any code change anywhere in my clojure file, and just knowing that clerk will do the right thing and evaluate exactly what needs to be evaluated. (and do it immediately, because all is cached in-memory) I do not need to think myself "which forms" to evaluate after a code change. I would even call this a new paradigm to work with Clojure apart from "repl first" and "clj-file first" π
This is super useful in any situation where evaluation of forms takes more then a second, so a blind "eval buffer" would be too slow. With Clerk we get a kind of "eval buffer", but it will only eval what is strictly needed , so what has changed and the dependencies of the changed forms. It avoids the need to actively decide which forms to evaluate after a change.
As forms in Clerk notebooks can be out of order, this can result in "notebooks" which are not "valid" clojure files, "valid" in the sense of failing to be running via
clj notebook.cljI would not call this being an "issue", but just a consequence of the way Clerk works.
Could you give an example?
I can have a valid notebook, where defs are out of order:
(def a (+ b 1)
(def b 2)Clerk evaluates and renders it, as it detect the order of dependencies.
Running the same as clj xx.clj will fail.
That's why clerk does not support redefining of defs... But we can detect this and fail on it. https://github.com/nextjournal/clerk/pull/92
Ohhh. Thanks
So that why Clerk is really a "different way" to render a "file full of Clojure forms"
π π
But ok, the forms above you can as well render in Cider doing the correct order by hand. So Clerk just automates this....
Otherwise said:
"valid" Clerk notebooks are not guaranteed to work via (require ...)
So they are not guaranteed to be valid namespace definitions.
Which is perfectly fine for "top level" files which are never required.
(this is different in notespace). An notespace file is always a valid namespace
actually, clerk wonβt eval this either:
(ns fw)
(def a (+ b 1))
(def b 2)
giving you
validate.clj: 28 clojure.tools.analyzer.passes.jvm.validate/eval2917/fn
MultiFn.java: 229 clojure.lang.MultiFn/invoke
validate.clj: 265 clojure.tools.analyzer.passes.jvm.validate/validate
validate.clj: 240 clojure.tools.analyzer.passes.jvm.validate/validate
Var.java: 384 clojure.lang.Var/invoke
passes.clj: 166 clojure.tools.analyzer.passes/compile-passes/fn/fn
passes.clj: 168 clojure.tools.analyzer.passes/compile-passes/fn/fn
passes.clj: 168 clojure.tools.analyzer.passes/compile-passes/fn/fn
passes.clj: 168 clojure.tools.analyzer.passes/compile-passes/fn/fn
core.clj: 2635 clojure.core/partial/fn
β¦it will work once youβve evaluated the (def b 2)
this should be true for Clerk and regular Clojure
But it would work after JVM restart, which in normal Clojure does not. (via clj file.clj)
But I agree that a 2 times (`cider-eval-buffer`) can make it work as well.
So not a big deal.
But I would somehow like to be sure that my Clerk notebooks can be run via clj from the command line.
@carsten.behring that still requires Clerk to be on the Java classpath, right? Otherwise no extra setup?
I've used an alias to add clerk as an optional dependency and then I launch my REPL using that alias for when I want to have clerk available at dev time without introducing a strict dependency on it.
Yes, but no extra setup needed.
The clerk/show! does both, evaluates the needed forms and send updates to browser.
Having it bound to a key is help full, if not the "files watcher" works as well (= evaluation on save)