Fork me on GitHub
#clojure
<
2020-11-18
>
fullNameHere04:11:20

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?

dpsutton04:11:16

probably best for #beginners but maps are not ordered

dgb2305:11:16

(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 https://www.oracle.com/corporate/features/understanding-java-9-modules.html into a clojure project ? By that I mean, structuring a large clojure project into Java 9 modules and composing them into services etc.

ghadi15:11:27

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 ?

murtaza5214:11:37

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

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

delaguardo14:11:00

you can use #'inc to avoid inlining

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

vlaaad14:11:40

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

delaguardo14:11:00

you can use #'inc to avoid inlining

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

borkdude14:11:22

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 [email protected]
            (finally
              (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

alexmiller15: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)

bronsa15:11:54

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

borkdude15:11:14

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

cap10morgan16:11:51

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.

nwjsmith17:11:33

I've experience a similar-seeming issue w/ Quartz before, maybe this helps? http://clojurequartz.info/articles/durable_quartz_stores.html#quartz_and_clojure_class_loaders

nwjsmith19:11:22

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

cap10morgan19:11:08

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

cap10morgan20:11:27

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.

schaueho17:11:58

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?

cap10morgan17:11:01

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

cap10morgan17:11:44

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

schaueho17:11:03

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

schaueho17:11:43

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

schaueho17:11:22

Clojure tools are also updated to 1.10.1.727

alexmiller17: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

alexmiller17: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

alexmiller17:11:07

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

schaueho17:11:05

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/

schaueho17:11:57

^^ it meaning clojure -X:project/new

seancorfield17:11:20

@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?

alexmiller17:11:48

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

alexmiller17:11:00

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

schaueho17:11:03

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

alexmiller17:11:53

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

schaueho17:11:03

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

alexmiller17:11:22

well there you go :)

alexmiller17:11:35

you probably have XDG_CONFIG_HOME set

alexmiller17:11:52

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

💯 3
alexmiller17:11:20

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

schaueho17:11:13

thanks a ton!

nod18:11:19

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:

nod18:11:14

{:version "1.10.1.708" 
 :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 ""}

noisesmith18:11:43

"can't use" - what specifically fails?

nod18:11:07

Yeah, sorry, I sent the message accidentally

nod18:11:15

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

nod18:11:37

This is the output for both clj and clojure

noisesmith18:11:53

"/usr/clojure" is a weird install location

nod18:11:04

I'm on OpenSUSE btw

nod18:11:25

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

nod18:11:00

I don't recall setting any paths manually

nod18:11:02

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

noisesmith18:11:58

so -Sdescribe is mistaken, or exposing some misconfiguration?

nod18:11:17

I suppose... How can I find out?

dpsutton18:11:15

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

noisesmith18:11:35

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

noisesmith18:11:52

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

noisesmith19:11:12

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

👍 3
noisesmith19:11:11

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

noisesmith19:11:02

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

nod19:11:48

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

nod19:11:11

Isn't it weird that lein repl works though?

noisesmith19:11:30

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

noisesmith19:11:49

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

noisesmith19:11:20

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

nod19:11:32

Oh, that makes sense

noisesmith19:11:20

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

seancorfield19:11:36

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.

alexmiller19: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.

nod19:11:50

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!

colinkahn21:11:56

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.

andy.fingerhut21:11:10

Compile-time is all of the time in Clojure 🙂

andy.fingerhut21:11:03

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.

colinkahn21:11:05

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

andy.fingerhut21:11:09

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.

andy.fingerhut21:11:12

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.

andy.fingerhut21:11:57

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

andy.fingerhut21:11:29

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.

colinkahn21:11:38

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.

andy.fingerhut21:11:38

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

andy.fingerhut21:11:51

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 🙂

colinkahn21:11:50

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

colinkahn21:11:32

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

andy.fingerhut21:11:06

welcome to monkey patching!

😅 3
oliver23:11:58

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 https://clojurians-log.clojureverse.org/beginners/2020-10-06. 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)

hiredman23:11:53

you should revisit assertion #1

hiredman23:11:26

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

oliver23:11:00

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

hiredman23:11:59

it is complicated

oliver23:11:22

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

hiredman23:11:27

so yes, it is possible I guess in the answer

hiredman23:11:52

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

oliver23:11:22

But then, according to https://www.reddit.com/r/Clojure/comments/8cs5hg/what_does_self_referential_dependency_mean_and/, the circularity might be in one of my dependencies (read: libs)

hiredman23:11:43

very unlikely

oliver23:11:20

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…

oliver23:11:45

(thanks for taking the time btw)

hiredman23:11:28

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

hiredman23:11:36

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

hiredman23:11:26

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

hiredman23:11:07

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

oliver23:11:25

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…

hiredman23:11:45

I doubt it is a build tool issue

hiredman23:11:36

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

hiredman23:11:29

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

oliver23:11:33

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?

hiredman23:11:56

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

oliver23:11:16

pr? pull request?

hiredman23:11:42

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

oliver23:11:51

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

oliver23:11:43

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))

hiredman23:11:03

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

oliver23:11:44

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

noisesmith23:11:53

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

oliver23:11:20

running lein check now…

hiredman23:11:54

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

oliver23:11:01

using lein run generates the following “full report”

hiredman23:11:35

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

oliver23:11:59

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.

noisesmith23:11:16

that has nothing to do with circularity

oliver23:11:23

@hiredman I'll run your command right now

hiredman23:11:01

it may print out a lot

oliver23:11:05

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

oliver23:11:49

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

hiredman23:11:00

sure, after you run it call start

hiredman23:11:22

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

hiredman23:11:45

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

oliver23:11:51

Yep… got a big printout

hiredman23:11:37

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

oliver23:11:43

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 clojure.tools.logging clojure.tools.cli guestbook.handler}, guestbook.db.core #{conman.core mount.core guestbook.config next.jdbc.date-time 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}, next.jdbc.date-time #{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}, clojure.tools.logging #{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}, clojure.tools.cli #{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)

hiredman23:11:09

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

✔️ 3
oliver23:11:07

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

oliver23:11:53

Ok… this is really embarrassing…

oliver23:11:18

`(:require [next.jdbc.date-time] [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])`

hiredman23:11:24

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

oliver23:11:53

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

hiredman23:11:13

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

👏 3
oliver23:11:19

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

oliver23:11:05

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

oliver23:11:50

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

oliver23:11:10

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

oliver23:11:35

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

dpsutton23:11:21

what's the hypothesis?

dpsutton23:11:28

we've come so far on this journey 🙂