This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-02-05
Channels
- # announcements (17)
- # architecture (5)
- # babashka (12)
- # beginners (155)
- # calva (18)
- # chlorine-clover (2)
- # cider (57)
- # circleci (2)
- # clojure (151)
- # clojure-europe (4)
- # clojure-gamedev (20)
- # clojure-italy (18)
- # clojure-nl (4)
- # clojure-norway (3)
- # clojure-spec (8)
- # clojure-uk (95)
- # clojurescript (70)
- # core-async (68)
- # css (3)
- # data-science (13)
- # datascript (1)
- # datomic (16)
- # docker (2)
- # figwheel-main (41)
- # fulcro (34)
- # graalvm (6)
- # graphql (7)
- # jobs (14)
- # joker (2)
- # kaocha (1)
- # leiningen (2)
- # malli (3)
- # midje (2)
- # overtone (1)
- # reagent (8)
- # reitit (6)
- # ring-swagger (1)
- # schema (2)
- # shadow-cljs (6)
- # spacemacs (3)
- # specter (5)
- # timbre (3)
- # uncomplicate (1)
Am I missing something or is apply
really this slow? What would be an efficient way to get the minimum from a collection?
(time
(dotimes [_ 1000000]
(apply max '(1 3 5 7 9 2 4 6 8))))
;; => "Elapsed time: 429.3991 msecs"
(time
(dotimes [_ 1000000]
(apply max [1 3 5 7 9 2 4 6 8])))
;; => "Elapsed time: 274.5674 msecs"
(time
(dotimes [_ 1000000]
(max 1 3 5 7 9 2 4 6 8)))
;; => "Elapsed time: 9.2664 msecs"
(reduce max Coll)
was in between those speeds in my testing
faster than apply by about a factor of 4 to 4.5
I don't know the details of exactly what JVM byte code the Clojure compiler turns it into, but max is annotated with nary-inline
and that name might mean that (max 1 3 5 7 9 2 4 6 8)
is in-lined by the compiler in some way.
You can take a peek at the bytecode: https://github.com/clojure-goes-fast/clj-java-decompiler/blob/master/README.md
I do not know yet, but the relationship between the time of using apply vs. not might differ as the collection sizes get larger, i.e. a lot of the time difference here might be one-time setup on calls. If you really want to use collections this small, then you care about that effect. If you really want to use much larger collections, you may want to benchmark with those instead. The Criterium library is recommended for benchmarking, as it will handle JIT warmup kinds of issues for you.
@U0CMVHBL2 Yes, reduce is in between.
(time
(dotimes [_ 1000000]
(reduce max [1 3 5 7 9 2 4 6 8])))
;; => "Elapsed time: 58.445 msecs"
Note that the time you show for (max 1 3 5 7 9 2 4 6 8)
is only 9.2 nanoseconds per call, which seems maybe impossibly quick, e.g. perhaps the value is actually calculated once, and simply returned each time through the dotimes, and mostly what you are measuring there is the overhead of the dotimes iteration loop.
Try comparing against the time to execute (time (dotimes [_ 1000000] (+ 5 7)))
, for example.
Or even (time (dotimes [_ 1000000] 5))
@U0CMVHBL2 Tangential question: will we at some point switch to Clojure 10 source code links in ClojureDocs?
I would guess yes, but when is up to the maintainer of the ClojureDocs site, which is not me.
https://github.com/zk/clojuredocs/issues/198 I created an issue requesting it
and someone made significant progress in that direction, mentioned in a PR linked from a comment there.
Thanks! Based on some of your earlier replies, I mistook you for one of the maintainers. At least you contributed extensively to ClojureDocs.
I am very glad someone else created it, and I refer people to there frequently.
Thanks for all the help on my question to serialise stuff! I'll have a look at transit and nippy. Are there any preferences when the main criteria is easiness to extend to non-standard datatypes?
they should be about equal - with transit you pass the data conversion rules as an argument to the write / read functions (which I like, it means you don't need to mess with a global state of registered readers / writers)
all else being equal I opted for transit as it has the option of semi-readable format (useful when debugging a live env by eg. peeking a kafka topic or naiive logging), and transit is from the core clojure team
Hi! Following a tutorial, thereās this piece of code that should get me clojure.set as set in scope, but when I try to compile, I get an error.
(ns pegthing.core
(require [clojure.set :as set])
(:gen-class))
2. Unhandled clojure.lang.Compiler$CompilerException
Error compiling src/pegthing/core.clj at (1:1)
#:clojure.error{:phase :macro-syntax-check,....
1. Caused by clojure.lang.ExceptionInfo
Call to clojure.core/ns did not conform to spec
whatās wrong with that syntax?Thatās it! Nice, thank you. Thereās a typo in the book then š
I think that older clojure versions used to work with (require
even though specifications/documentation didnāt allow for that.
Oh, ok, thatād make sense.
Good to know, thanks!
Also related. Is there something in the direction of array-set
? For context, I am working on some debugger and the order of things in maps/sets is importent.
Essentially I want to read the sets/maps as sets/maps or at least know that they were sets/maps and be able to traverse them in the order they were defined.
I see that there is https://github.com/clj-commons/ordered
Up to 8 entries, but you shouldnāt rely on that
@alexmiller but there is no way to modify this threshold ? Is there a way to obtain a similar behavior for small sets?
no, it's hard-coded
maps and sets are not ordered, full stop
relying on implementation details will make you broken
(eventually)
what problem are you actually trying to solve?
@alexmiller I am working on the cider-nrepl debugger and the instrumentation of map/set literals. I guess for map literals with more than 8 entries we have to use some heuristic.
heuristic for what?
you described a context not a problem...
@alexmiller The debugger reads normal clojure forms and instruments them for debugging. Currently it uses the nesting of the expressions (kind of location information) as a way to give back feedback to the user. The problems with maps/sets is that the order of the expressions is not preserved. For example something like (read-string "#{(inc 2) (inc 3)})"
gives {(inc 3) (inc 2)}
. I just would like to know if there is a way to avoid this problem. Hope it makes sense now. For literal maps, the order is preserved up to 8 entries as you mentioned.
Yes, that helps
I think to do it the best way, you would need to replicate the readerās code and either change whatās happening or track more
There are other Clojure parsers out there that might be a better match for your goals though
Really what youāre doing here is parsing, not reading
That is, the goal of the reader is to turn text into Clojure data. You really want to turn text into ast (parsed structure)
Those are similar but different goals
The analyzer May be more than you need
Other people have written parsers for tooling
Also more of a meta question when should one ask here and when is it ok to ask #clojure ?
Is (load filename) the correct way to pull in other files with their own namespace? If so, is there some kind of init function that needs to be present? I tried swapping load-files out for loads while breaking a project into namespaces and it told me I'm missing a init class.
usually, you should use require
to initiate loading
and not use load
or load-file
directly
Ah, cool. I didn't realize that would work for files that were hanging out in my project instead of being defined in the project.clj
well, you haven't shared enough other info to determine whether you are in or out of "usually" here
require
will use the classpath to find the namespaces, so it depends on having your source files in the classpath, in a directory corresponding to the namespace
if that's not true, load-file
is probably most straightforward. load
is classpath focused, but has rules about how things are found based on its doc string
so just switching from one to the other probably requires changing the argument path
Ah, ok. The file structure is src/project-name/several-files-each-with-a-name-space so project.core loads and expects to be able to load project.server, for instance. This is just how the project ended up, I can move things to get require to work.
Hey everyone, Sorry to interrupt. I've been struggling with a Clojure deploy error for more than a week. Please take a look at: https://stackoverflow.com/questions/59938002/java-lang-noclassdeffounderror-for-clojure-java-api-clojure I would really appreaciate any advise. I do not know what to do anymore. Tks!
I did. Clojure classes are not at Tomcat's or system's own libraries. I also created a script to list all .class on the classpath and compared with my application libraries. No duplicated entries were found.
Almost certainly something related to the context classloader. Also, there were some changes in Clojure 1.10.1 vs 1.10.0 to mitigate a Java issue introduced in Java 1.8.0 u201 (give or take, donāt remember precisely). Any Clojure version diff between them?
Good call. I am using Clojure 1.9.0. I will try 1.10.1 instead.
@alexmiller Sorry... Let me correct myself. We've tried 1.10.0 and 1.10.1 already and got the same error. It was the first thing we did. No luck.
ok, good to check on that at least
your stack trace indicated that clojure failed static initialization, not that the class wasn't found
this exception indicates:
Caused by: java.lang.NoClassDefFoundError: Could not initialize class clojure.java.api.Clojure
Yep. I've inspected the source code of clojure.java.api.Clojure but did not find anything unusual.
any chance you have a user.clj file somewhere?
on the classpath
I do not. Should I?
no, but that affects early initialization
just checking it wasn't on one but not the other
is ClojureHandler source somewhere?
I've inspected the source code at Github. I am using the official distribution.
can you point to it?
com.nitryx.brkmopt.util.ClojureHandler
oh.. sorry. Yes. This is my program.
Let me copy the line that throws the error for you. Just 1 min...
there is almost certainly an exception thrown during the static initializer of clojure.java.api.Clojure - whatever that is would probably point to the problem. the trick is getting to it.
more than the line would be helpful
presumably the line is loading the Clojure class :)
there it is:
public static Object invoke(String ns, String function, Object... parameters) {
IFn func = Clojure.var(ns, function);
Object ret;
int n = parameters.length;
switch (n) {
case 0:
ret = func.invoke();
break;
case 1:
ret = func.invoke(parameters[0]);
break;
the line that throws the Exception is:
IFn func = Clojure.var(ns, function);
(Sorry for the interruption) I have a global state that needs to be modified by multiple threads. More specifically, I have a map that will have a key/val pair added to it some amount of times (always a new key/val pair), but from a separate thread (or threads). Whatās the most idiomatic way to implement this in Clojure? Should I be using transients, or some other type of thread-safe protection (e.g. atoms)?
atom holding a map
Got it, thank you.
transients are explicitly not safe to use in threaded code, and shouldn't really be passed between functions in most code
well, first - what ns / function is it
@bfabry yes... thats the problem. The very same app. Just in case, I will print ns in the log just to be sure if we are not missing something.
This is the same .war. The same build. On different servers.
Different loading order for classes, causing the ns
to be required (and loaded) on one server but not the other?
Looking again the code. ns cannot be the problem. It is hardcoded.
you could try loading the Clojure class earlier - maybe in the static initializer of ClojureHandler for example. like
static {
Class.forName("clojure.java.api.Clojure");
}
@seancorfield ns is "com.nitryx.brkmopt.opt.scenario". I do not see how the order would make difference because it is something I created. But it was a good call.
@alexmiller trying your suggestion right now. I'll get back to you shortly. Thanks very much.
I notice that Tomcat 8.5.50 includes a Catalina that has a big slew of "Correct a regression in the static resource caching changes..."
perhaps Tomcat 8.5.49 is bad - have you tried bumping up? (or going back to 8.5.37)
Ohh... nice! I'll try it too.
@rodrigo759 could you share the whole stacktrace? Isn't there really anything interesting apart from what you shared in https://stackoverflow.com/questions/59938002/java-lang-noclassdeffounderror-for-clojure-java-api-clojure ?
something with resource caching/loading could certainly break Clojure, which loads clj files as resources
@jumar I am editing the stackoverflow post to include the full stacktrace
@alexmiller my team is changing Tomcat as we speak.
I have a reaction gif ready for if a critical detail was being elided from the stacktrace
Full stacktrace is there.
I couldn't find anything more there.
You could perhaps try to run the same tomcat version on both servers or, better, reproduce it locally.
And perhaps -verbose:class
JVM arg could give you some helpful details about classloading.
Also make sure you're not running out of memory (just in case)
@alexmiller YES! Downgrading Tomcat to 8.5.37 did the trick. Not easy because other apps are running in production using version 8.5.49. I had to convince the customer's IT guys that I need this version. So far, so good. Thank you all very much. @alexmiller, do you have a Stackoverflow account? If you do, you might want to publish the solution. I will accept and upvote it.
I keep sending my stackoverflow points to my mortgage company but the exchange rate for fake internet points is terrible
Do they accept karma?
apparently not
Hah! I love that line originating this thread. I should copy and save it somewhere. Reminds me of a similar idea phrase I have sometimes used, when people compliment you for your abilities and knowledge, but what you really want is respect and/or better salary "That and 50 cents will buy me a soda"
I need to block in my main thread until another thread has a value that I need to continueāessentially just blocking until I get a message. How should this be done?
Or is it more likely Iām looking at this problem the wrong way, and thereās a better solution or something like that.
Huh. Was looking through https://clojure.org/reference/ā¦, didnāt think that that wouldnāt include core.async. Thank you.
Noob question here. How to I get the value passed in because % doesn't seem to work here
(-> (GetResult url)
(let [body (:body %)] (println body)) )))
% is a special syntax inside #()
just use a let for that:
(let [res (GetResult url)
body (:body res)]
(println body))
or (-> url (GetResult) (:body) (println))
is (-> url (GetResult) (:body) (println))
the preferred way or (as-> (GetResult url) % (:body %) (println %))
the first one - though you might prefer to move url
over into the GetResult call (it expands to the same thing)
most people would actually do (-> (GetResult url) :body println)
- same result still
Any opinions about http://purelyfunctional.tv? Sorry for posting the link, let me know if I have to remove it. Iām thinking about getting a membership to learn clojure but would like to hear opinion of somebody thatās used it
I regularly use it to get details on things that I haven't done before, though I wasn't a Clojure beginner when I first got my membership - over the years I've generally used it to get a bit more detail on specific topics rather than watching all the content. I recently went through a lot of the re-frame content and found it to be excellent - one of the best resources I've seen for that. I would totally recommend trying it out and seeing if it works for you. There is also https://lambdaisland.com/, which has a bit different style and quite a bit less content, but the content that is there is generally very good as well.
Thatās an awesome review, thank you very much. Iām not new to functional programming concepts in general, but I just started learning clojure and am trying to figure out the most efficient way. Guess Iāll just give it a shot š
Yeah, if that's where you're coming from there should be a lot of great content for you. Hope it helps!
The REPL-Driven Development course on http://PF.tv is definitely worth at least one month of membership. It's awesome.

http://purelyfunctional.tv and lambdaisiland have excellent quality for learning Clojure. I also have over 60 hours of Clojure videos, these are less polished but then they are free š https://practicalli.github.io/ I also find the https://clojuredesign.club/ an excellent resource for thinking functionally
Nice! The only thing I donāt really like about functionaltv is the organization of website. It was hard for me to find the āintroduction to clojureā course and tbh Iām not sure what will my next steps after finishing it look like š
Thanks for the links, Iāll give them a look!