This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-01
Channels
- # announcements (3)
- # aws (1)
- # babashka (56)
- # beginners (42)
- # calva (9)
- # cider (6)
- # circleci (5)
- # clj-kondo (17)
- # cljs-experience (1)
- # cljsjs (2)
- # clojure (106)
- # clojure-australia (1)
- # clojure-europe (36)
- # clojure-germany (5)
- # clojure-italy (13)
- # clojure-nl (14)
- # clojure-spec (19)
- # clojure-uk (27)
- # clojurescript (27)
- # cursive (20)
- # datomic (24)
- # events (2)
- # fulcro (11)
- # graalvm (1)
- # jobs (6)
- # lsp (6)
- # malli (5)
- # meander (36)
- # membrane (17)
- # nbb (4)
- # nextjournal (86)
- # off-topic (18)
- # pathom (3)
- # polylith (5)
- # portal (14)
- # rdf (5)
- # re-frame (5)
- # releases (6)
- # remote-jobs (3)
- # reveal (2)
- # ring (6)
- # shadow-cljs (171)
- # tools-deps (61)
- # vim (10)
- # xtdb (6)
I'm looking for a way to write a service library with self-contained migrations to a given postgres schema, configured at the app level, the app depending on the service lib. It seems like flyway might support this via classpath stuff. Has anyone tried it before in a clojure project? https://smyachenkov.com/posts/flyway-migrations-in-multi-module-maven-projects/
It is answering partially for your question. It is possible to “manage” flyway from Clojure.
deps {com.github.metaphor/lein-flyway {:mvn/version "6.0.0"}}
(ns db.flyway
(:require [flyway.flyway :as fw]
[api.db.postgres :as postgres]))
(def flyway-db (fw/flyway {:url postgres/db
:locations ["filesystem:dev-resources/db/migration"]}))
(defn restart-db []
(fw/clean flyway-db)
(fw/migrate flyway-db))
(defn wrap-test [tests]
(restart-db)
(tests))
(comment
(restart-db))
ah, that's helpful, I think 'locations' could be a hook into it. I would need my own build/deploy scripts around this.
i’d suggest using https://github.com/yogthos/migratus. migratus migrations are just resources on the classpath
ah I see, their docs didn't have it but the code can use classpath resources: https://github.com/yogthos/migratus/blob/master/src/migratus/migrations.clj#L106
ya i think they’re assuming resources
is already on your classpath (it’s a pretty standard top-level directory).
Trying to straddle microservices and monolith by using a shared DB per deploy, with some reusable things packaged up as libs, replacing SQS, SNS, scheduling with just postgres when the scale is small.
https://gist.github.com/qnkhuat/997d8da99e88f7967b8719982802af73 I wrote a simple Mnist reader in Clojure, Could anyone give me some ideas on how to make it faster?
I just did a simple time
with 2 reader func. How should I profile it?
Sorry, I don’t have time to analyse it deeper, but maybe one of this steps to improve performance https://clojure.wladyka.eu/posts/how-to-improve-algorithm-performance/ will be useful for you.
Time does not profile. A tool like clj-async-profiler will let you see where you spend CPU
There are things I can tell you to do which will make it faster but you won't know why
So profile first, understand what's going on, and then you'll be able to ask more relevant questions
unfortunately, I couldn’t profile because I’m using mac M1.
Tried it with a Linux machine but hit some permission issues setting up clj-async-profiler
Will try to find a linux machine tmr 😕
A few things to look at: Primitive type hints in the loop Avoid using r/map, you can map in place over the array Create a vector directly with vec and not into
So I tried with your suggestion:
1. Primitive type hints in the loop => this adds a bit of performance but not much (from 1564ms to 1445 ms)
2. Avoid using r/map, you can map in place over the array => I’m not sure what you mean by map inplace
- is it?
3. Create a vector directly with vec and not into => So instead of doing r/map
I used map
and mapv
. Pretty interesting mapv
gives a 30% performance bump
Here is analysis with time
(still can’t run profiling 😞 )
Read an array of 47.040.000 elements
;; "Elapsed time: 1564.851583 msecs" (r/map without type hint)
;; "Elapsed time: 1475.194334 msecs" (r/map with type hint)
;; "Elapsed time: 1143.0205 msecs" (use mapv instead of r/map)
;; "Elapsed time: 6397.154542 msecs" (use map instead of mapv)
Ah, seems like the data allocated is too large compared to the operation I do with it: which is only to-unsigned? This is one minor case where immutable is not shine?
It's okay but done pretty inefficiently, I'll profile allocation, too, see what's dominating it Also not sure if your test was reliable as partition is lazy, maybe doall should be called on it
yep, that partition
is definitely lazy.
Is *warn-on-reflection*
a ns-specific declaration or does it apply to all required namespaces as well?
as most commonly used (after the ns form), it's just for that namespace
(btw, your screen name is a Clojure function homonym - when-some
)

Is there a way to set it for the whole project, or do I just need to annotate every ns?
you can set it from your repl in a project and it'll apply to all nses, right?
The reason it only applies to the one ns is that it gets bound in the require code, right? So the set!
only lasts for the binding for that call
yes, it's bound during the load then that context is popped
thanks
there is not currently a way to turn it on for a whole project. if you set it in your repl, it will apply to all subsequent loads, so you could probably leverage that to check all. I think maybe lein does something like that
we do somewhere have an ask clojure question or ticket about this (turning it into a compiler setting)
linters like clj-kondo will also warn you about this too of course
reflection
that would be a neat feature
there is however an issue to give a warning when you're doing Java interop, to set warn-on-reflection to true: https://github.com/clj-kondo/clj-kondo/issues/686
maybe I'm confusing it with warnings built into cursive, nvm!
perhaps clj-kondo could do that, but then it has to become as good in following type hints as the clojure compiler, and I don't want to create any false positives... maybe as an experimental linter.
I think I would normally turn it off. In normal Clojure programming, reflection is good for legibility & productivity at no cost to the results. Where reflection is a "legality" problem, Java will let me know.
> at no cost to the results The cost is performance and out of the box GraalVM compatibility
Is this expected behavior, or a bug?
Clojure 1.10.3
user=> (dissoc (sorted-map "a" 1 "b" 2) :c)
Execution error (ClassCastException) at user/eval1 (REPL:1).
java.lang.String cannot be cast to clojure.lang.Keyword
I see a handful of bug tickets concerning thrown exceptions related to sorted-map, so I wonder if this is another.Yeah, I think it makes sense that if you have a sorted set, you must have only keys that are comparable to each other, and trying to dissoc something that isn't comparable with the keys erroring makes some sense.
other tickets related to sorted-map and exceptions: https://clojure.atlassian.net/jira/software/c/projects/CLJ/issues/?jql=project%20%3D%20%22CLJ%22%20AND%20text%20~%20%22sorted-map%20throws%22%20ORDER%20BY%20created%20DESC
sorted maps/sets are inherently limited to what their comparator can compare, and the default comparator is not a universal comparator.
I can understand after the fact why it would be throwing, based on an incompatible Comparator. But it surprised me that it breaks (in my opinion) the contract of dissoc
. Also, there is no mention of this behavior in the docstring for either sorted-map
or dissoc
I'm not sure that the door is fully closed on this, but in general we have not tried to "protect" users from exceptions arising from the use of key values not covered by the comparator
Yeah, I’m not claiming this is a bug, just asking. On the flip side, there is clearly no other option for assoc
than to throw an exception. It would seem worse to silently not assoc in the case of a different key type
there's no way external to the comparator function to know what is allowed, so doing so would require try/catching around use of the comparator and falling back to some "not found" behavior
I think a note in sorted-set / sorted-map docstring would be justified
Yeah, I agree. Something like “Collection operations performed on the sorted map may throw exceptions if an incompatible key type is provided”.
Does anyone know of a parallel/concurrent some
? Same as some except that done in || and no extra work done as soon as a result is found.
So you could do this by chunking a sequence and making a work queue with all the chunks in it, spinning up a thread pool to take chunks and chew through them with the predicate, and the first one to find something empties the work queue and returns the value to the original thread, but as far as I'm aware this has not yet been implemented and published anywhere.
Although personally I'd make this function return only true
and false
because multiple runs of it may return different values otherwise.
You could so something like this
you could turn that final loop
into a go-loop
in order to make this return asynchronously as well
if you want the impure "return a value that matches the pred" you could change the cond to save the result from some
and return that after setting the work-queue to nil, change :else
to return nil, and change the if at the end to be (if (some? res) res (recur ...
instead
Doing stuff I don’t know much about, and most certainly not getting interested in calculating primes, but given:
(decompile
(let [m (bit-shift-right (long 1024) (long 6))
n (bit-set 1024 6)
o (clojure.lang.Numbers/setBit 1024 6)]
nil)
)
using the clojure goes fast clj-java-decompiler
I get this (somewhat abbreviated)
public static Object invokeStatic() {
final long m = 1024L >> (int)6L;
final Object n = ((IFn)core$fn__14806.const__4.getRawRoot()).invoke(core$fn__14806.const__5, core$fn__14806.const__3);
final long o = Numbers.setBit(1024L, 6L);
return null;
}
So what confuses me here is that it seems like bit-shift-right
gets compiled down to simple java operator stuff, whereas neither bit-set
or Numbers/setBit
get the same treatment. Why would that be?Clojure intrinsics
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Intrinsics.java - some Clojure functions that are replaced with bytecode
So in order to make @pez win his all clojure prime sieve, could we have some more bit ops intrinsics 🙂
If you have to generate a mask using shift and then and, or maybe even a second mask to invert the first and then and
But you could imagine (but probs not with todays impl of intrinsics) that you could emit the equivalent of the impl in operators, but I guess the JIT probably just inlines this anyhoop
static public long setBit(long x, long n){
return x | (1L << n);
}
Just curious, what tool do the members here use for developing in Clojure?
https://www.surveymonkey.com/results/SM-S2L8NR6K9/ Question 16 of the state of clojure survey should offer some insight (Emacs, here)
I use doom emacs, which has cider, clojure-lsp, kondo, and the default way to do structural editing in doom is with lispy, but I really don't like lispy so I use evil-cleverparens.
I start with the latest git branch of emacs-28+native compilation+xwidgets with Mitsuharu Yamamoto’s patches for MacOS and then add CIDER, clj-refactor, smartparens (and an emacs config evolved over 30+ years). For those who are using clojure-lsp, what does it add over CIDER? how do you deal with overlapping features in CIDER?
why do people write (:k m)
instead of (m :k)
for map lookups? by habit, this leads to generic lookups being written as (k m)
which invariably blows up when somebody gets clever.
(x :k)
- is it :k
in map x
or function x
with parameter :k
?
(:k x)
- it is :k
in map x
Yeah, so writing (map key)
is fine. Writing (:key map)
is fine. But in general if you're having generic keys I would prefer (get map key)
(def m nil)
(m :k) ;; java.lang.NullPointerException
(:k m) ;; nil
1. nil punning
2. (:k m)
supports a default value, like get, e.g. (:k nil 0) ;=> 0
- edit:`(m :k 2)` also works, as long as m is not nil
3. functions typically operate on data structures, so thinking of keywords as functions that operate on a map seems more intuitive to me than having maps be functions of keywords (even though both make sense mathematically) - there are exceptions though, e.g. (map m ks)
looks better than (map #(get m %) ks)
or (map (fn [k] (k m)) ks)
or ((apply juxt ks) m)
edit: oops, just saw there was a discussion outside the thread as well, sorry for repeating most of the points@UEQPKG7HQ On your second point: all forms of map retrieval allow for a default value:
user=> (def m {:a 1})
#'user/m
user=> (m :b 2)
2
user=> (:b m 2)
2
user=> (get m :b 2)
2
Right, thanks for the correction (I updated my comment)!
If m
is a proper map but the key you're looking for is missing, my point is moot but if m is nil, you'd get a null pointer exception with (m :b 2)
You're right though, in the core of it it's the same argument as nil punning, I just meant to illustrate a different aspect of it; the reader might expect that (m :b 2)
and (:b m 2)
are equivalent ("if :b
is not found in m, return 2") when they're not.
one reason is that (let [m nil] (m :foo))
will throw an NPE whereas (:foo m)
will not
yeah, that’s true. lesser of two evils I suppose
there was a good thread a while back talking about this kind of thing. I was kinda parroting the advice from Zach Tellman to use the most concrete bit as possible. Like (contains? some-set value)
to aid in readability. But others pointed out that using the flexibility of Clojure has lots of benefits as well. ie, (some-set value)
lets you use functions, maps, etc. And leveraging that is a benefit. So the NPE is one consideration, but not the end of the decision to me