Fork me on GitHub

Hey guys, a little confused by this behavior. (defn vector-X-Long [x] (loop [itr 0 arr []] (if (= itr x) arr (recur (inc itr) (conj arr itr))))) (defn create-data [dates] (->> dates (map (fn [x] {x {:booked? false :nameOfEvent :nothingBookedYet}})) (into {}))) (def lost (create-data (vector-x-long))) Why doesnt this return the hashmap in order. ex. {0 {}, 1 {}, 2 {}, 3{} ...} Instead it returns what feels like randomness. When I println x inside create-date its in order. How could I get it for (def lost) to be in order?


probably best for #beginners but maps are not ordered


(seq {:a 1 :b 2 :c 3 :d 4})
=> ([:c 3] [:b 2] [:d 4] [:a 1])

(seq (into (sorted-map) {:a 1 :b 2 :c 3 :d 4}))
=> ([:a 1] [:b 2] [:c 3] [:d 4])

Rhishikesh Joshi11:11:44

Is anyone here aware of any work done to integrate into a clojure project ? By that I mean, structuring a large clojure project into Java 9 modules and composing them into services etc.


Pretty much everyone ignores modules

Rhishikesh Joshi15:11:31

Ok 🙂 What would be the preferred method to organise a large Clojure project and get features like dependency management and modularisation between groups of namespaces, without going down the road of full fledged libraries and services ?


(with-redefs [inc (fn [v] (+ 2 v))]
  (inc 2)) 

=> 3
what am I doing wrong ? (I was expecting 4)


you can use #'inc to avoid inlining

(with-redefs [inc (fn [x] (+ 2 x))]
  (#'inc 2)) ;; => 4


maybe (inc 2) is inlined, hence the compiled code doesn’t do var dereferencing at all


you can use #'inc to avoid inlining

(with-redefs [inc (fn [x] (+ 2 x))]
  (#'inc 2)) ;; => 4


Hackety hack:

(def inlined (atom {}))

(defmacro un-inline [var-sym & body]
  `(do (swap! inlined assoc (var ~var-sym) (:inline (meta (var ~var-sym))))
       (alter-meta! (var ~var-sym) dissoc :inline)
       (try ~@body
              (alter-meta! (var ~var-sym) assoc :inline (get @inlined (var ~var-sym)))))))

(un-inline inc
           (with-redefs [inc dec]
             (prn (inc 1)))) ;; 0

(with-redefs [inc dec]
  (prn (inc 1))) ;; 2

Alex Miller (Clojure team)15:11:37

keep in mind even that won't work if you call something in core that calls inc, because it's pre-compiled (with direct linking)


I mean, even w/o direct linking it would've already been ... inlined


yeah, you would have to reload those namespaces in the body of un-inline. veery hacky


I'm trying to use Clojure to write a Sonarqube plugin (which expects Java). I have it loading my plugin, but then it crashes with Could not locate clojure/core__init.class, clojure/core.clj or clojure/core.cljc on classpath presumably b/c it loads plugins in their own isolated classloaders but Clojure uses its own (or something like that; I'm a bit out of my depth here). Anyone run into something like that before? Clojure and spec are in the jar file in META-INF/lib, so it seems to be related to the classloader thing.


I've experience a similar-seeming issue w/ Quartz before, maybe this helps?


@U06FS3DLH did you end up getting this all worked out?


I did not. Thanks for the link! Reading it now.


hmm... interesting. I'm not sure anything like this exists in Sonarqube (what I'm trying to write a plugin for), so I'm trying to set Clojure's classloader to the one Sonarqube is using for the plugin. It gives a custom classloader to each plugin.


As a leiningen user so far, I've come across practicalli/clojure-deps-edn and wanted to try it on a new piece of code. However, on a simple clojure -X:project/new I just receive an error message: No function found on command line or in :exec-fn. Searching the tubes for this doesn't reveal anything helpful -- any idea what might be wrong here?


@schaueho I think you will need to setup your ~/.clojure/deps.edn file correctly for that to work.


Looks like the example deps.edn in that GH repo has what you want.


well, I followed the instructions on the practically/clojure-deps-edn repo and so my ~/.clojure/deps.edn actually contains a :project/new alias


that's why I'm puzzled why it doesn't work


Clojure tools are also updated to

Alex Miller (Clojure team)17:11:29

I copied the :project/new alias from that repo into my ~/.clojure/deps.edn and was able to successfully run clojure -X:project/new so must be something in the setup

Alex Miller (Clojure team)17:11:50

clj -Srepro -Sdeps '{:aliases {:project/test {:replace-deps {seancorfield/clj-new {:mvn/version "1.1.226"}} :exec-fn clj-new/create :exec-args {:template lib :name practicalli/playground}}}}' -X:project/test

Alex Miller (Clojure team)17:11:07

^^ can you try that one-liner? it ignores your ~/.clojure/deps.edn


it also works when I copy the deps.edn file to a separate directory and run the command from there, so I guess somehow the deps.edn is not getting picked up from ~/.clojure/


^^ it meaning clojure -X:project/new


@schaueho Maybe there's a typo in your ~/.clojure/deps.edn file? Could you share it, or at least part of it that's relevant to this issue?

Alex Miller (Clojure team)17:11:48

can you clj -Sdescribe and look at the output to see if :config-user points at ~/.clojure/deps.edn ?

Alex Miller (Clojure team)17:11:00

could be different if you have $CLJ_CONFIG or $XDG_CONFIG_HOME set


@seancorfield it's a clone of the current practically/clojure-deps-edn repo that I didn't edit

Alex Miller (Clojure team)17:11:53

I checked the practicalli/clojure-deps-edn file and it works fine for me


@alexmiller actually it doesn't, it points at :config-dir "~/.config/clojure"

Alex Miller (Clojure team)17:11:35

you probably have XDG_CONFIG_HOME set

Alex Miller (Clojure team)17:11:52

in that case, config will be at $XDG_CONFIG_HOME/clojure

💯 3
Alex Miller (Clojure team)17:11:20

you can override that by setting CLJ_CONFIG to your ~/.clojure if you want


thanks a ton!


Hey, I probably did something stupid and can't use either clj or clojure . lein repl still works fine. Could anybody help me figure it out? clojure -Sdescribe output:


{:version "" 
 :config-files ["/home/myuser/.clojure/deps.edn" ] 
 :config-user "/home/myuser/.clojure/deps.edn" 
 :config-project "deps.edn" 
 :install-dir "/usr/clojure" 
 :config-dir "/home/myuser/.clojure" 
 :cache-dir "/home/myuser/.clojure/.cpcache" 
 :force false 
 :repro false 
 :main-aliases "" 
 :repl-aliases ""}


"can't use" - what specifically fails?


Yeah, sorry, I sent the message accidentally


Error: Could not find or load main class clojure.main Caused by: java.lang.ClassNotFoundException: clojure.main


This is the output for both clj and clojure


"/usr/clojure" is a weird install location


I'm on OpenSUSE btw


If I'm not mistaken I just installed it via YaST2's GUI (which I suppose is OpenSUSE's official way)


I don't recall setting any paths manually


I just checked, /usr/clojure doesn't exist


so -Sdescribe is mistaken, or exposing some misconfiguration?


I suppose... How can I find out?


Is opensuse Debian based? I know there’s a package there called clojure that is a bad wrapper


opensuse is derived from redhat, but split a long time ago


the debian clojure just wraps clojure.jar, and has none of the cli features, yeah


it wouldn't be able to produce the "-Sdescribe" output

👍 3

@edjroot you could try downloading from and installing the scripts to ~/bin or /usr/local/bin- it's pretty simple


beyond what it provides, all it needs is java to be on path


Alright, I'll do that and let you know if it works, thanks!


Isn't it weird that lein repl works though?


not at all - clojure is just a jar that you put on the java classpath


it doesn't use any global installation that clj / lein would share


both use .m2 to cache deps, but that isn't used for clojure itself on startup


Oh, that makes sense


getting down to the basics, clojure is a java library, providing a clojure.main class with a -main entrypoint that runs a REPL compiling clojure code to bytecode and running that bytecode


Since there's a brew tap for clojure/tools/clojure that is maintained by the Clojure team, I've found it worth installing linuxbrew and using that to keep my CLI install up-to-date.

Alex Miller (Clojure team)19:11:27

fyi, homebrew core tap is now being kept up to date with stable releases from clojure/tools/clojure. and linux tap is tracking that one, so while there is a lag of couple days for each hop there, they should all be showing you approximately the same thing these days.


So, before trying the CLI method I actually uninstalled and installed it again via YaST2 and now it works... Go figure 🙂 Thanks a lot for the quick and helpful responses!


Is it possible to change what a var points to at compile time? Example is I want to replace clojure.core/memoize with my own version.


Compile-time is all of the time in Clojure 🙂


The smiley is there because it isn't strictly true, but it is true that whether you are loading code from a file or entering expresssions at a REPL, all top level forms are compiled before they are evaluated. You can use things like alter-var-root to modify the root binding of a Var. If there is a call to that at the top level in a file that you load or require, then it will be evaluated and take effect while loading/requiring that file.


This is what I wasn’t sure about. Like most uses of memoize will be (def my-fn (memoize my-fn*)) , so it seemed like it would be too late to catch those cases if I just alter-var-root


If you do not compile Clojure with direct linking, which is disabled by default, then whenever memoize is called, it will dereference the Var's current value.


That is why in a REPL you can use defn to redefine a function foo, and with a few exceptions, other functions defined earlier that call foo will call the updated version.


Oh, in your case, you will want to make sure that alter-var-root is evaluated before you evaluate that def form.


Because using alter-var-root after such a def form, yes, memoize will have been deref'd at the time that def form is evaluated.


OK, then I will give it another go but try to be more careful about when it’s called. Basically I’ll need to alter-var-root before I do any requires of code that will use it.


There may be easier ways to do it in your code base, but if you have some kind of utils namespace that is require'd by most or all of your namespaces, you could put the alter-var-root in there and know that it will take effect before any namespace that require's that one


Then again, if you have that, then you could instead define your own memoize-like function, and call it instead of clojure.core/memoize throughout your code base, but I'm guessing if you were willing to do that, you wouldn't have asked 🙂


In this case I’m actually trying to target a third party lib.


But I think I can create an entrypoint where I do setup and then do a (require …)


welcome to monkey patching!

😅 3

Hi! I'm follwowing the current beta of Dmitry Sotnikov's Book on Luminus. I have started over three times by now due to a bug that leaves me mystified, but that inevitably seems to creep up  at some point. I get the following error when I try to start the application (once the REPL has started): Execution error (AssertionError) at ns-tracker.dependency/depend (dependency.clj:57). Assert failed: self-referential dependency (not (= x dep)) As far as I can remember, on each occasion the last thing I did before this happened was wiping one of my database tables – hardly something that I'd expect to lead to an NS-problem. Here's what I know: 1. I definitely have no circular dependencies among my own namespaces 2. All I did was manipulate the DB. Most imortantly none of my clojure namespaces have changed. 3. The Problem is related to Ring's `wrap-reload` middleware, which apparently does it's own dependency-checking. When I remove it from my dev-middleware-chain everything works (except reloading, obiously). I can also create an uberjar without problems. I know that certain people discourage the use `wrap-reload`  in general (as Sean Corfield did in reply to a However, I can hardly believe that this kind of error is intractable to the point that I have to switch build tooling… Any ideas on where this might stem from? (edited)


you should revisit assertion #1


because that error indicates ns-tracker (which is used by wrap-reload) disagrees and thinks you do


Is it really possible to compile the project into an uberjar in that case?


it is complicated


Well… I guess the circularity might only be resent in the dev-build…


so yes, it is possible I guess in the answer


and ns-tracker and clojure itself may not agree on how they detect circularity


But then, according to, the circularity might be in one of my dependencies (read: libs)


very unlikely


hm… I can, of course re-check, but as I said: None of my Clojure source-files have changed… only in CLJS… and even there the ns declarations did not…


(thanks for taking the time btw)


one of the reasons some people discourage the use of things like wrap-reload is the code reloading is a complicated thing to do, and the state you get into with reloading is very unlikely to be exactly the same as the state you get when starting the system fresh


so if you have been going on and everything has been working fine using reloading for a while, then you kill and restart the process for some reason, and then things are broken, the change that caused the breakage could have been sometime ago and just happened to continue to work with reloading for whatever reason


but I would strongly suggest you go over your code with a fine tooth comb before you start looking at libraries


like, I've seen things where people where trying to debug something not behaving as they expected and it ended up they had two checkouts of the code and were editing and running different checkouts


I understand that… actually I'd even prefer to use something a bit simpler (not albeit not easier than leiningen): My first go was with boot… but I found my progress greatly hampered by dealing with build troubles 60% of the time when my actual goal was to grok Luminus…


I doubt it is a build tool issue


the assertion that is failing is a check that fails when a namespace literally depends on itself


like if you had (ns foo (:require foo))


I gathered as much (I have dealt with circular dependencies on quite a number of occasions before)… I'll check again… I guess there's no way to find out which ns is actually offending?


there is a pr on the project to include the offending ns in the message


pr? pull request?


what steps exactly do you take before you see the error?


ok, sorry if this is a dumb question… so the project you're talking about would be Ring?


Ok, thanks for you patience: here's how I reproduce it: 1. Jack-in CIDER → REPL Starts, all good so far 2. In user ns: (start) 3. I get this: 2020-11-19 00:27:38,376 [nREPL-session-d79a4c6f-7e7b-4cf4-bed5-9bb3c6896d1d] INFO guestbook.env - -=[guestbook started successfully using the development profile]=- Execution error (AssertionError) at ns-tracker.dependency/depend (dependency.clj:57). Assert failed: self-referential dependency (not (= x dep))


depending on what steps happen before you get the error, you may be able to run code before the error happens, which will allow you to change the definition of the function throwing the error to print out its arguments before throwing the error which will tell you which ns it is


I get something more detailed when I do it on the console with lei run (which also uses the dev profile)


there's also lein check which simply loads up every clj file on local path, and it should hit an error and report it, it definitely tells you which file blew up


running lein check now…


run (alter-var-root (requiring-resolve 'ns-tracker.dependency/depend) (fn [orig] (fn [& args] (prn args) (apply orig args)))) before calling start


using lein run generates the following “full report”


the last thing that gets printed out will include the name of the offending namespace


lein check shows no errors… just one warning that does indeed smell a bit of “circularity”: Reflection warning, guestbook/core.clj:56:42 - call to java.lang.Thread ctor can't be resolved.


that has nothing to do with circularity


@hiredman I'll run your command right now


it may print out a lot


(thanks again to both of you for your time and patience)


@hiredman your command returns a function #function[user/eval29638/fn--29639/fn--29640]


sure, after you run it call start


then you'll get print outs of the arguments to the depend function as ns-tracker uses it


and the last print out will be the arguments it is called with before the assertion error


Yep… got a big printout


the arguments will generally be a list, the first element being a big map, the rest of the arguments are namespace names


The last thing printed is this: ({:dependencies {guestbook.routes.home #{guestbook.validation struct.core guestbook.layout guestbook.middleware ring.util.http-response guestbook.db.core ring.util.response}, guestbook.handler #{mount.core guestbook.layout guestbook.routes.home reitit.ring ring.middleware.content-type guestbook.env guestbook.middleware ring.middleware.webjars}, guestbook.middleware.formats #{luminus-transit.time muuntaja.core}, guestbook.core #{guestbook.nrepl mount.core guestbook.config luminus-migrations.core luminus.http-server guestbook.handler}, guestbook.db.core #{conman.core mount.core guestbook.config next.jdbc.result-set}}, :dependents {guestbook.validation #{guestbook.routes.home}, guestbook.nrepl #{guestbook.core}, conman.core #{guestbook.db.core}, mount.core #{guestbook.core guestbook.db.core guestbook.handler}, guestbook.config #{guestbook.core guestbook.db.core}, struct.core #{guestbook.routes.home}, #{guestbook.db.core}, guestbook.layout #{guestbook.routes.home guestbook.handler}, guestbook.routes.home #{guestbook.handler}, reitit.ring #{guestbook.handler}, luminus-migrations.core #{guestbook.core}, luminus.http-server #{guestbook.core}, luminus-transit.time #{guestbook.middleware.formats}, #{guestbook.core}, ring.middleware.content-type #{guestbook.handler}, muuntaja.core #{guestbook.middleware.formats}, guestbook.env #{guestbook.handler}, next.jdbc.result-set #{guestbook.db.core}, guestbook.middleware #{guestbook.routes.home guestbook.handler}, #{guestbook.core}, ring.util.http-response #{guestbook.routes.home}, #{guestbook.routes.home}, guestbook.db.core #{guestbook.routes.home}, ring.middleware.webjars #{guestbook.handler}, guestbook.handler #{guestbook.core}, ring.util.response #{guestbook.routes.home}}} guestbook.db.core guestbook.db.core)


so ns-tracker thinks guestbook.db.core depends on guestbook.db.core

✔️ 3

fascinating… ok… I'll have another look at this ns…


Ok… this is really embarrassing…


`(:require [] [next.jdbc.result-set] [conman.core :as conman] [mount.core :refer [defstate]] [guestbook.config :refer [env]] ;; [java-time :refer [java-date]] [guestbook.db.core :as db])`


more embarrassing then that guy who had two code checks and was editting one and running the other?


I have no idea how I managed to do an then miss this…


well, someday that pr will get merged and it won't be a big mystery

👏 3

I was actually looking for exactly this kind of thing (because it was what I understood the error to mean)


Still… I was lucky to have someone with a thorough knowledge ot ns-tracker's inner workings


I have an hypothesis as to how this came about… but I feel I've been bothering you long enough…


If we weren't in lockdown I'd buy you a pint…


Anyway: thanks again (looking forward to that pr)!


what's the hypothesis?


we've come so far on this journey 🙂