Fork me on GitHub

Does this definition make sense? Trying to make a wrapper similar to priority-map-keyfn without falling into pitfalls with custom comparators

(defn sorted-set-keyfn
  [keyfn & keys]
  (apply sorted-set-by
    (fn [a b]
      (let [c (compare (keyfn a) (keyfn b))]
        (if (zero? c)
          ;; break the tie consistently
          (compare (hash a) (hash b))


(sorted-set-keyfn count "Aa" "BB")
#_=> #{"Aa"}


sorted-set and sorted-map require total ordering because the comparator is also used for equality. hash can't be used to break ties because of collisions.


I don't know if there's any practical reason why partial ordering could not be supported though


huh, that's interesting - I had assumed hash collisions would be much harder to come by


Regarding this: I recently tried using clj-kondo metadata to find the subtree’s of ns dependencies that are referenced by my project, but I get weird errors when running with the classes directory on my cp. Stuff like ClassNotFoundException’s. One thing to note: the project uses ig/load-namespaces

Alex Miller (Clojure team)13:03:53

I don't know what that is

Alex Miller (Clojure team)13:03:06

if you are partially compiling things and missing things you depend on, it's possible to get into bad scenarios. what happens if you do what's in the guide?


I can’t literally do what is in the guide; because the app uses ig/load-namespaces; essentially the require tree is built dynamically by wiring in integrant config… esssentially stuart sierra’s dependency.


ig is for integrant

👍 4

can integrant be a red herring?


I’m not suggesting it is a herring; just that it and also perhaps the presence of tools.namespaces.repl/clear etc might be 🙂


load-namespaces just ends up calling require — same as ns macro ends up calling require


true — it’s really the use of integrant.repl/reset which causes me concern; rather than load-namespaces.


as that uses


though I suspect it’s probably me messing up in my suggestions of namespaces to compile


@alexmiller Yeah ok it makes total sense that compile assumes all transitive requires are also compiled. It’s most likely in my manual pass over the first results that I messed something up regarding transitive namespaces… I had to for example remove some shadow-cljs npm requires; and also some cljs namespaces etc by hand; as it’s a mixed clj/cljs project.


It remembers me of an old discussion related to calling lein uberjar (which adds compiled classes to the classpath) and then starting a REPL. Same class not found error and same relationship with having a component system in place. Never spent time to find the root cause, but now I always lein clean after uberjarring.


I might be misunderstanding the issue, but I think these problems are caused by :aot poluting other profiles. I always prevented that with: No idea why lein never made this a default option tbh; I’ve always set it.


Ah good to know. Will try soon

👍 4

Yeah that did it, good to know :thumbsup:


There's a lot of fear around aot. Tools namespace explicitly discourages it.


Random ClassNotFoundException was the exact reason I stopped using AOT for third-party libraries.

Alex Miller (Clojure team)14:03:21

there is a lot of irrational fear around aot


Yeah I’ve always AOT’d apps, never really had any issues with it; that weren’t issues worth fixing anyway… e.g. side effects happening at compile/load time.


Integrant with dynamic namespaces/components makes it somewhat more difficult though — I’ve been wanting to resolve that for a while.


One thing the startup time link above doesn’t discuss is the pitfalls of doing it… e.g. presumably an app that downgraded a dependency to a prior version might have some problems

Alex Miller (Clojure team)14:03:04

"Periodically, you will need to re-compile to account for new dependencies or changing code."

👍 4

> AOT-compilation: Reloading code does not work in the presence of AOT-compiled namespaces. If you are using AOT-compilation in your project, make sure it is disabled and you have deleted any AOT-compiled .class files before starting a REPL development session. (In Leiningen, run lein clean.) Another example of a potential gotcha would be the above, though is the statement from even accurate though? I suspect it’s more nuanced than it lets on. i.e. presumably reloading will work in the presence of AOT-compiled namespaces; so long as the namespace that is being reloaded isn’t itself AOT-compiled? Is that right?!

Alex Miller (Clojure team)14:03:47

without running experiments, don't know

👍 4

is there a way to use namespace aliases to creating a record that is defined in another ns?

(ns app.worker)

(defrecord WorkerA [x] ...)

(pr-str (map->WorkerA {:x 1})) ;; => #app.worker.WorkerA{:x 1}

(ns app.other
  (:require [app.worker :as w]))

#app.worker.WorkerA{:x 1} ;; works

#::w.WorkerA{:x 1} ;; doesn't work

Alex Miller (Clojure team)14:03:35

you should really prefer using the constructor functions, which are normal functions and can be accessed via aliasing in the same way as any other functions

Alex Miller (Clojure team)14:03:13

so here (w/map->WorkerA {:x 1}) would work fine


right. Just checking for completeness. Thanks, Alex

Alex Miller (Clojure team)14:03:11

the #app.worker.WorkerA is a syntax for a Java class name constructor and Java class names have nothing to do with namespace aliasing


Definitely I've experienced AOT issues. AOT on your app is fine, uberjar style. But for libraries it's caused us issues in the past for sure


Mostly because compile is transitive


So what happens is you end up if dependency A uses B v1, and you depend directly on A and B v2. Then the AOT jar of A will actually contain the compiled classes of B v1

Alex Miller (Clojure team)15:03:12

that does not seem right. by what process would that happen?


that’s an AOT uberjar, no?


No it's not. That happens just if you compile A and jar the classes-dir folder

Alex Miller (Clojure team)15:03:50

that seems like a bad process

Alex Miller (Clojure team)15:03:05

not blaming you or anything


Ya, it is. What I did at work was we now have a custom jarring. So it'll filter through the classes-dir and select only classes of the package to Jar.


> That happens just if you compile A Would the same happen if you run compile with the same classpath that your app has?


No, it would be fine then


But only if you had A as a source deps


The issue is, libraries publishing their Jars should not be AOT compiled, or if they are, should be very careful about what compiled classes they put in the Jar they vend


Hmm. Still at a loss then for why I was seeing ClassNotFoundException from time to time when I was trying to compile the whole all.


Hum.. in the REPL?


Part of that error would depend on how you launch the app


If it's started where the classpath to the JVM doesn't point to all the needed dependencies this would happen


Not in the REPL, no. The classpath is exactly the same.


Exactly the same?


If you expect to use a generated class from gen-class for example, the classpath post compile must now include the compiled classes


Or it won't find them


But Clojure requires shouldn't be broken, even if they don't find the classes they fallback on the source


import might, like I said. As the classpath must point to the compiled classes


Well, yeah, I think the only difference was the "classes" dir. Apart from that, the classpath was exactly the same. Most of the time, it wasn't able to find manifold.deferred.IDeferred which is a definterface.


Those kind of errors I feel are always super mysterious


I’m making a form to upload a file. Simple stuff, only a field for a name, and a field for uploading. I already have some code in place to do this:

[:input {:type "file" :name "uploaded-file" :required ""
                    :accept ".xls, .xlsx, .ods, .csv, .tsv, .pages,
                             application/, text/csv,
but if someone uploads a file through an android phone, they can still upload e.g. a pdf. Am I doing something wrong in that accept attribute? If not, is there a way to do it server-side without adding cljs to my project?


You can't use that as validation


This is part of the HTML 5 spec


Which means it's a matter of each browser supporting it or not


You could always find a browser that doesn't support it


I think it can also be really finicky to find the correct combination of attributes for different browser and OS as well


ah makes sense.. I’m new to this 😄 cool, so I actually need some JS to do this


Well... To be honest. That part I'm not so sure either


The file picker is not normally something you have direct control over


I'm not sure if JS will be able to configure it anymore


But you will be able say, after the user picks a wrong file extension in the file picker, to do a quick client side validation before the file is uploaded (I think)


Otherwise you can do the same on the server side, though that means the file has to be fully transferred and all that


It can probably help you at this point to Google for HTML file accept or like how to restrict file selection of input file, etc.


Nothing should be Clojure specific


This one seems to have good info


In the case where B is not vending itself as AOT


So because B is not compiled


The compile of A will transitively include all of B


And all those classes will go on the classes-dir


And then get Jared as a lib (not uberjar)


And then when you depend on A, you get the classes of B as well. And if A depends on a different B, and because B is a source lib, and Clojure load favours classes over sources you will get the version of B defined by A

Alex Miller (Clojure team)15:03:41

yeah, that seems like a problematic way to do aot, but I see how you get there

Alex Miller (Clojure team)15:03:22

aot'ing from an app namespace makes you dependent on the classpath, which has already been resolved with version selection (only B v2 is available)

Alex Miller (Clojure team)15:03:52

seems like if you are running all your compile's in that classpath context, same would be true right?


Yes, but A specifies a dependency on B v1

Alex Miller (Clojure team)15:03:20

what tooling were you using for this or was it something custom?


So the classpath resolves to B v1. And then A is AOT compiled


And then my App depends on A and B v2

Alex Miller (Clojure team)15:03:56

but the classpath will not resolve to B v1 here


It won't, but the Jar of A will have classes of B v1 in it


And Clojure Load will see that each namespace on B v2 (whose Jar only has sources) also have a .class on the classpath coming from A's Jar

Alex Miller (Clojure team)15:03:07

maybe I was misunderstanding what you were talking about then. are you talking about publishing aot'ed library artifacts? or a process for aot'ing an app?


I'm talking about publishing AOT libs

Alex Miller (Clojure team)15:03:56

and if you do, they should only include that lib's classes


Yeah this is with custom tooling. But I remember looking what lein does and it seemed it would suffer the same faith

Alex Miller (Clojure team)15:03:33

yeah, it is very easy to do it wrong (and it takes away choices from a downstream app builder)

Alex Miller (Clojure team)15:03:49

compiled classes are inherently dependent on some version of the clojure compiler

Alex Miller (Clojure team)15:03:04

if the lib compiles, the app doesn't have the opportunity to pick that


Ya, that's what I meant by libraries shouldn't be AOTed.


Application can and I've never had issues there

Alex Miller (Clojure team)15:03:06

ok, then we are in violent agreement :)

👍 4
Alex Miller (Clojure team)15:03:17

sorry I misunderstood :)


No worries, honestly it hurts my brain everytime I try and rethink about this issue. Dependencies are so hard


For us, we had a case of a dependency doing AOT because it also gen-classes itself so it can be consumed by Java and Clojure


So that was even more fun to deal with! 😅

Alex Miller (Clojure team)16:03:36

a couple of the contrib libs actually publish both source and aot versions (the latter under aot classifier)

Alex Miller (Clojure team)16:03:22

well, actually clojure itself too has a "slim" version that is source-only


I did face this issue with Clojure actually. When going from 1.9 to 1.10 I think. We had a library that was doing an AOT for a gen-class. Even though it was only compiling the gen-class namespace and that had no requires. Transitively, it would compile the only sources not AOT compiled in Clojure 1.9, the core specs.


And somehow on 1.10 some core macro changed in a way that the 1.9 spec would fail to validate calls to it


So we were getting the 1.9 specs of Clojure indirectly through this.


Was very confusing haha


Anyway, our solution now is our build have you list out the namespace you want to gen-class explicitly. And it will do an AOT of them, and then select only the classes file of that namespace and not of any transitive dependencies. And only include that in the Jar

Alex Miller (Clojure team)16:03:16

that's how basically all aot tooling ends up working

Alex Miller (Clojure team)16:03:56

that's what we do with the maven clojure plugin for the contrib libs


Ya, I feel I had checked what lein did and it didn't appear to do that. Like it does only AOT the gen-class namespaces. But then it packages everything resulting from that into the Jar

Alex Miller (Clojure team)16:03:06

yeah, I think lein is really targeted more towards the app casee

Alex Miller (Clojure team)16:03:30

but it's been a while since I looked at it


I should go see what the maven contrib Clojure plugin does. Might be some good learnings in there

Alex Miller (Clojure team)16:03:17

the config is pretty fiddly to make it do exactly what you want

Alex Miller (Clojure team)16:03:07 is the tools.reader config which is fairly complicated as it's both building a source jar, then aot'ing, and building an additional aot'ed jar with the assembly plugin


I do think I'm seeing some of the code that cleans up the classes that weren't for the declared namespaces, seems this does it here:


Hello, everyone. If anyone here uses vim, can you tell if it's normal for clojure to have different rules about how words are defined? Currently, for me, w pretty much behaves the way I'd expect W to work, and * and # match along similar definitions? I've had some plugins installed from when I tried clojure years ago and I don't know if I've missed one as I've progessively uninstalled everything Clojure or Lisp related


I do not know the answer. I suspect you may get some useful replies here, but wanted to point out that in case not, there is also a #vim channel that may be more likely to reach knowledgeable folks in that area.


Many thanks, I'll ask there


Did not get the 1.0.0 treatment?


Should still be considered production ready, right? What with one stable and one alpha version. BTW the fact that I’m asking is a good indicator that the 1.0.0 move was a right one :)

Alex Miller (Clojure team)20:03:56

I would use the alpha right now


Hello, Does anyone know how to add and configure gatling-maven-plugin in project.clj


lein doesn't use maven, and I wouldn't assume a maven plugin would be useful in a lein project


that said you could make a pom.xml (or even run lein pom to make a project pom) and configure it there


this would mean using maven in parallel with lein (or instead of it)


if lein does not use maven, why is the plugin available as lein deps


the plugin itself is a maven artifact, lein knows how to resolve and download the artifacts (using the underlying aether lib), but it doesn't use the maven executable which is what you need for maven plugins


lein uses the same artifact cache / download setup as maven but doesn't run maven plugins


Hi all,curl -X GET ' '"' -H 'API-Key:MySecret'


that was not supposed to happen dmanit


oooooh that string doesn't look like it should be on a public slack channel 😛


yes - it fortunately only a test one


hopefuly it is gone now?


what a mistake!!!! GRRRR


when I use this on a cli curl -X GET '"' -H 'API-Key:MySecret' I get the correct results in clojure snippet ((client/get "" {:body-encoding "UTF-8" :accept :json :jwt ["API-Key" "MySecret"]})) it fails now it might be the auth-type is a jwt but I cannot tell - I have tried all variations of :auth-type "oauth1" :auth and similar and cannot get it right what am I doing wrong? I have been all over the clj-http github docs but ....


why are you putting what should be a header into a :jwt key?

Nir Rubinstein21:03:57

:headers {"API-KEY" "SECRET"}


:headers {"API-KEY" "SECRET"} results in failuer Key must be integer


hold typo? on my side?


"key must be integer" means that some clojure function is doing a map lookup but you gave it a vector


hello everyone. can someone direct me to whom is in charge of keeping the ubuntu leiningen package up to date?


2.9.1-2 is listed


i tried sudo apt install leiningen-clojure but no dice...maybe im using the wrong command tho


and sudo apt install leiningen gives me 2.8.1


have you updated? sudo apt-get update


correct i have


$ sudo apt-get install leiningen
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 13.0 MB of archives.
After this operation, 14.9 MB of additional disk space will be used.
Get:1  bionic/universe amd64 leiningen all 2.8.1-6 [13.0 MB]


Does lein upgrade not work after installing from apt?


correct it says that upgrade is intended to be used outside of a package manager install


which is a bummer


Ah, then I'd go with noisesmith's suggestion of just installing it manually.


is showing 2.8.1


but i would like 2.9.1


will bionic forever be on 2.8.1?


lein is very easy to manage outside the ubuntu package management system: you put a shell script in ~/bin/lein and then use lein upgrade X to make it run a specific version

✔️ 4

ok i will try that then!


it's just the one file (and of course making sure that file's directory is on path), as described on that page


so this file is lein and it does not install on the machine?


the file is a wrapper script that uses a local cache for holding the actual jar and launching a java process


it's both the script and the downloader, in one




does it have to be on the path? i assume if i ran the file like ./bin/lein it would install it on the machine, no?


no, it does no installation of the script itself, of course it can be run via absolute path but it doesn't put itself on path


hmmm ok sorry im getting confused by like

Run it (lein) and it will download the self-install package


^ makes me assume it will download lein on my machine


it downloads a jar that it uses


ok cool i think im understanding


thanks @U051SS2EU for your patience w me!


Yes it works thanks - the docs stated [`"API-KEY" "SECRET"] not {"API-KEY" "SECRET"} many thanks`


but it results in a 401 Unathorised


in your original you had API-Key - is it picky about case?


that is my bad typing


So no it is not the case


I have it consistent in the actual test item


I have tried the :digest-auth [api secret]/ the aws version/ etc.... so it is very frustrating


if the curl you showed works none of that is even relevant


that is what I find odd


I have also used httpie and got a result


Other docs on a sister site stated they use jwt but as you state - the keys are in the header


if you really want quality help, and to value people's (free) time, - Post what the intent was - Post the code you ran - Post the error you received (in full, don't leave out things you don't think consider helpful)


like be really specific, rather than saying stuff like "it failed" or "it worked"


otherwise it's the Miss Cleo school of debugging

😂 8

thanks, at 9:30 I hope i did state the problem - it is one line of clojure where I am attempting to covert a curl call to clojure and I do not understand how I convert it - It seems the api keys are referred in the header and I am using the clj-http library for the one line of code and attempting to get the syntax right . There is not much else except I receive 401 responses.


As a noobie in clojure I wish I knew how to look under the covers so to speak


If you're really just getting started with Clojure, you might have better luck asking in #beginners -- folks there will show you more patience and will be more forgiving...


This channel tends to assume a certain level of scientific method in debugging etc and some solid ability to read source code in libraries...