This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-11-18
Channels
- # aws (1)
- # babashka (35)
- # beginners (52)
- # biff (4)
- # calva (55)
- # cider (19)
- # clojure (54)
- # clojure-dev (3)
- # clojure-europe (23)
- # clojure-nl (1)
- # clojure-norway (3)
- # clojure-uk (2)
- # clojurescript (9)
- # code-reviews (3)
- # datahike (1)
- # fulcro (1)
- # funcool (4)
- # graalvm (21)
- # gratitude (2)
- # java (5)
- # jobs (2)
- # joyride (1)
- # kaocha (13)
- # malli (2)
- # off-topic (22)
- # other-languages (11)
- # pathom (4)
- # re-frame (35)
- # reagent (3)
- # reitit (3)
- # releases (2)
- # remote-jobs (1)
- # rum (1)
- # shadow-cljs (42)
- # sql (18)
- # tools-deps (72)
- # web-security (6)
- # xtdb (15)
;; ns x
(def foo "something")
;;ns y
(def foo x/foo)
;;ns z
(println y/foo)
Changing the value of x/foo
to "something else"
requires reevaluating y/foo
otherwise ns z doesn't pick up the change. This was a bit unintuitive but I suppose it is expected because vars != refs (?)... I get the same behaviour when x/foo
is a function.
Is there a cider function that will reload all of the nses in between automatically? cider-load-buffer
and cider-ns-refresh
don't work.If you use integrant -then you can use a library called https://github.com/weavejester/integrant-repl - that will detect all files that have changed and reload them correctly according to their dependency graph. I have it set to a hotkey in emacs.
Thanks, I'll check it out!
I thought cider-ns-refresh
was supposed to do that as well (both use clojure.tools.namespace
under the hood)
I'm starting to suspect there's something wrong with my setup :thinking_face:
This is why sometimes you'll see things like:
(ns x)
(defn foo [] "something")
(ns y)
(def foo #'x/foo)
(ns z)
(y/foo)
Now, if you change x/foo
, you will always get the newest value, since y/foo
is a reference to the var and not a specific implementation.
BTW: This works kind of by magic, because Clojure will silently deref vars if you treat them as function calls. If foo
was a def
not a defn
in namespace z you would need to first deref: @y/foo
I think a good example of this in practice is in the reitit docs, where it shows how to differentiate between a dev router (recompiling on request/save/whatever) and a production router (compiled and memoized). https://cljdoc.org/d/metosin/reitit/0.5.18/doc/advanced/dev-workflow?q=dev#an-easy-fix
Notice in particular, that if you think through the cases where this kind of behavior may be beneficial (dev vs prod, dynamic vs static) - you can architect a REPL-friendly system without having to rely on specific tooling (like integrant-repl or clojure.tools.namespace.refresh).
> you can architect a REPL-friendly system without having to rely on specific tooling (like integrant-repl or clojure.tools.namespace.refresh). Indeed! To be honest I'd rather not use either 🙂
try
(def ^:dynamic *pretty-objects*
"If true, cider prettifies some object descriptions.
For instance, instead of printing functions as
#object[clojure.core$_PLUS_ 0x4e648e99 \"clojure.core$_PLUS_@4e648e99\"]
they are printed as
#function[clojure.core/+]
To disable this feature, do
(alter-var-root #'cider.nrepl.print-method/*pretty-objects* not)"
true)
i think this is the default pretty printer?
(clojure.pprint/pprint (.getBytes "foo"))
[102, 111, 111]
https://docs.cider.mx/cider/usage/pretty_printing.html#configuring-a-printing-function
❯ clj
Clojure 1.11.1
user=> (require '[clojure.core.server :as server]
'[clojure.string :as str]
'clojure.test
'clojure.pprint)
nil
user=> (clojure.main/repl
:prompt (fn [] (printf "%s=> " (peek (str/split (str *ns*) #"\."))))
:eval (fn [f] (binding [clojure.test/*test-out* *out*] (eval f)))
:read server/repl-read
:print clojure.pprint/pprint)
user=> (.getBytes "foo")
[102, 111, 111]
user=> :repl/quit
nil
user=> (.getBytes "foo")
#object["[B" 0x3bb8aabc "[B@3bb8aabc"]