Welcome! Please see the About page for a little more info on how this works.

0 votes
in Namespaces and vars by
edited by

I was surprised that this code in dev/user.clj doesn't run at start up:

(ns user) ; user ns is loaded by REPL startup

(println "Evaluating dev/user.clj")
(when-not (resolve 'xxx)
  (def xxx 1)
  (println "defing xxx"))

This worked for me:

(defonce yyy (let [tmp 1] (println (str "deffing yyy as " tmp))

Something like this was also suggested to me in the clojurians
[https://clojurians.slack.com/archives/C053AK3F9/p1683882344251029][Slack] :

(ns user)

(when-not (resolve 'xxx)
  (intern 'user 'xxx 42)
  (prn "!!!"))
This is the kind of thing I want to achieve in dev/user.clj

(require '[portal.api :as portal])
(defonce p
  (let [tmp (portal/open)]
    (add-tap #'portal/submit)

Dang, just realised this isn't actually going to help with the multiple portal windows opening. They are obviously still going to open when I rejack in. :-|

But the language question stands.

1 Answer

+1 vote

Without seeing your full project I can’t be certain, but I am guessing that your user namespace is configured to be AOT-compiled (compiled to a Java class ahead of time, rather than being compiled from Clojure source at startup time). When that happens, the compiler often optimizes things that can be done at compile time instead of startup time, so your println probably happens once when the project is being compiled, rather than every time your application is run. This often trips people up who are trying to do things like capture the time an application started in a var; they end up seeing the last time the project was compiled.

Understanding the lifecycle of top-level forms can be tricky and subtle, especially when it comes to compilation and the interaction between Clojure and the JVM. Not having to grapple with them is one of the benefits you can derive by adopting a state-management library like Component or system.

Here is my deps.edn:


The code in question is in dev/user.clj and should run when I jack in:


Calva allows me to copy the jack in command it uses to the clipboard and here it is:

pushd /Users/jamiep/Documents/clj/euler ; clojure -Sdeps '{:deps {nrepl/nrepl {:mvn/version,"1.0.0"},cider/cider-nrepl {:mvn/version,"0.28.7"}}}' -M:dev:portal -m nrepl.cmdline --middleware "[cider.nrepl/cider-middleware]" ; popd
Ah, we’ll have to let someone else pick up the discussion then, I still use Leiningen as my Clojure builder and launcher, so I don’t know what is AOT-compiled in the deps.edn world.