This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-10-14
Channels
- # announcements (1)
- # asami (3)
- # aws (1)
- # babashka (22)
- # beginners (39)
- # calva (21)
- # clj-kondo (10)
- # cljdoc (22)
- # cljs-dev (17)
- # clojure (93)
- # clojure-australia (3)
- # clojure-europe (39)
- # clojure-italy (3)
- # clojure-losangeles (17)
- # clojure-nl (14)
- # clojure-russia (2)
- # clojure-uk (5)
- # clojurescript (35)
- # community-development (7)
- # conjure (2)
- # cursive (13)
- # data-science (1)
- # datomic (25)
- # emacs (5)
- # events (4)
- # figwheel-main (2)
- # fulcro (12)
- # graphql (7)
- # gratitude (2)
- # inf-clojure (6)
- # leiningen (6)
- # lsp (49)
- # malli (13)
- # membrane (30)
- # minecraft (1)
- # pathom (3)
- # pedestal (26)
- # polylith (13)
- # portal (2)
- # quil (3)
- # random (1)
- # re-frame (13)
- # reagent (43)
- # reitit (6)
- # releases (1)
- # reveal (2)
- # ring (3)
- # shadow-cljs (30)
- # specter (5)
- # sql (8)
- # tools-build (1)
- # tools-deps (13)
- # videos (1)
How can I read a text file in batches of n lines? Is there a simple way of doing this?
You can use line-seq
to get a lazy sequence of lines. That's probably a good start.
It would depend on how exactly you want to consume/process it. What are you trying to do with those batches of lines?
You can partition-all
the line-seq
, for example.
So, what problem are you actually trying to solve here?
OK. So I'd probably structure that as
(run! transact-batch (partition-all n (line-seq source)))
transact-batch
would be invoked with a sequence of n
lines at a time (except for the last batch which may be smaller).
It could then use next.jdbc/execute-batch!
to insert a block of n
rows into the database.
If you need each line parsed into data suitable for the DB:
(run! transact-batch (partition-all n (parse-line (line-seq source))))
(it's morning for you but after midnight here so I'm off to bed but feel free to post any follow-up Qs and I can answer when I'm awake again)
This is a mystery:
(do
(def p (java.util.Properties.))
(def ^:const btst4 {:k p})
(:k btst4))
; => IllegalArgumentException: No matching ctor found for class java.util.Properties
But if I remove the ^:const
it starts working. Any idea what is happening? (Clojure 1.10.1 and 1.10.3)The exception (for me) is thrown in this line: https://github.com/clojure/clojure/blob/b8132f92f3c3862aa6cdd8a72e4e74802a63f673/src/jvm/clojure/lang/Reflector.java#L308 My interpretation is that it finds multiple constructors with the same arity, but none matches the parameter type?
I’m wondering about what args are assumed there, but I don’t have a setup which can debug into Java Code
last time I checked ^:const
isn't documented in http://clojure.org, it's simpler and better documented to use direct linking
Same here, I couldn't find it there. Worth direct linking you mean ^:inline?
Thank you. If direct linking is a compiler flag then it isn't really relevant here. I am trying to define a map with rather static config options, that's why I marked it with const. I guess I will try to debug it as @U0N9SJHCH proposed to see what really is happening and whether or is a Clojure bug
^:const
does not prevent the referenced object from changing. It simply tells the compiler that the var itself will not be changed.
it's weird because it works with classes like HashMap
(def x (java.util.HashMap.))
(def ^:const bar {:foo x})
(:foo bar)
With Properties you don't even need to call it, hell you can't even wrap it in try-catch. I think it dies somewhere in the bowels of the compiler
(def x (java.util.Properties.))
(def ^:const bar {:foo x})
So far so good, but then
(defn check [] (:foo bar))
dies without ever calling (check)
Also, it works if you wrap it in a (defn…)
And Java 8 returns a different error message than Java 11
This is not a place where I would expect const to work
Use const when you have something like a number or a string you want to inline during compilation. Almost anything beyond that is probably a misuse
Ah, ok, good to now :-) I thought it would make the field static final or something.
The inconsistency bugged me.
https://github.com/clojure/clojure/blame/master/src/jvm/clojure/lang/Compiler.java#L7329-L7330
Seems like const stuff get quoted? Then I assume evaled at some later point?
Thing is that even (eval {:k (java.util.Properties.)})
results in the same error. I added a ton of debug statements in the Reflector and for some reason it can't find the no-args constructor of Properties?
ctor public java.util.Properties(java.util.Properties)
params class java.util.Properties
args {}
ctor public java.util.Properties(int)
params int
args {}
I can't seem to replicate this with other java.util classes (and I tried with a few that aren't used in the Clojure source), so no idea why it only breaks with PropertiesThese are two different things, but I think you're misunderstanding both of them.
With const, you're saying that the value is a conpile-time constant and the compiler can replace the var reference in the bytecode with the literal value
In the eval case, I'm not sure exactly what you're seeing there, but it feels like the fallback case the compiler uses to round trip arbitrary objects through bytecode by using print/read
Hm that makes it more clear. Any idea why it behaves differently with Properties and for example BitSet?
no, without spending time I don't really have atm to find out. Properties is one of the worst classes in the JDK and it has a lot of eccentricities.
Hmmm... what could be wrong here?
(map key t)
=> (:4 :1 :2 :5 :3)
(name :4)
=> "4"
(map (name key) t)
Execution error ...
clojure.core$key cannot be cast to clojure.lang.Named
That's a nice solution 🙂
is there any way to lexicographically sort list ("john" "harry" "anne") into ("anne" "harry" "john")
Be careful when you sort collections of strings:
(sort ["John" "anne" "Harry"])
;; => ("Harry" "John" "anne")
Depending on the desired result you might want to sort-by
lower-case
Is there any library to "memoize" a function using Redis as the caching backend? I found the "crache" library, but it's broken
I wouldn't imagine so since there are a few competing redis libraries and no clear winner
but it shouldn't be that hard to write - just decide how you want to serialize your function's arguments and result to store in redis
You could probably write a Redis backend to core.cache
-- it's designed to be extensible.
I am currently trying to do so, by trying to fix "crache", but so far I am failing, the last argument passed to CacheProtocol/miss
seems to be a function from core.memoize...
core.cache
does not depend on core.memoize
-- but core.memoize
does depend on core.cache
.
deps.edn:
:build {:paths ["src"]
:deps {io.github.clojure/tools.build {:git/tag "v0.6.2" :git/sha "226fb52"}}
:ns-default build}
build.clj:
(ns build
(:require [clojure.tools.build.api :as b]
[shadow.cljs.devtools.api :as shadow]))
(defn uber [_]
(clean nil)
(shadow/release :app)
(b/copy-dir {:src-dirs ["target" "resources"]
:target-dir class-dir})
(b/compile-clj {:basis basis
:src-dirs ["src"]
:class-dir class-dir})
(b/uber {:class-dir class-dir
:uber-file uber-file
:basis basis}))
Hi I have success in combining the cljs compilation part with clj to get a uber jar file. Question: is there a way to default the .jar to a main class instead of
java -cp xyz-1.2.2-standalone.jar clojure.main -m xyz.core
I'd like to use just
java -jar xyz-1.2.2-standalone.jar
yes, you can use the :main
key in b/uber
see https://clojure.github.io/tools.build/clojure.tools.build.api.html#var-uber
(and btw, you might find #tools-build to be good for future questions like this)
(b/uber {:class-dir class-dir
:uber-file uber-file
:basis basis
:main 'xyz.core})
is this correct?There's a compile-clj
function in tools.build
It's shown in @zengxh’s build.clj
above (further up).
Interesting; I was receiving an error from graalvm when trying to create a native image even though I was using AOT. I might have done something else incorrectly.
Well, it's "just" compilation, but it is being done before building the uber JAR so it is "AOT" in that respect.
$ java -jar xyz-0.1.4-standalone.jar
Error: Could not find or load main class xyz.core
Caused by: java.lang.ClassNotFoundException: xyz.core
$ java -cp xyz-0.1.4-standalone.jar clojure.main -m xyz.core
<OK>
@zengxh You also need to ensure that your main class is compiled and that it has (:gen-class)
in its ns
form for that namespace.
(I think a lot of people miss that last part)
compile-clj
with that i thought i could get away without gen-class
. i never really understand gen-class 😳
:gen-class
causes -main
to become a static main
method in the class compiled from the namespace.
really, it causes all -foo methods to become static, just most importantly -main :)
Yes, I was being deliberately vaguely/over-simplified here 🙂 :gen-class
is a veritable Swiss Army Knive!
(otherwise it's just compiled Clojure code that can be called from Clojure, rather than directly from Java)
I tend to miss it almost every time I write a new "main" namespace. Then I compile and build the uber JAR and go "Oh, rats! I forgot :gen-class
again!" 🙂
I often wish it was a special case that defn -main
always became a static main
method 🙂
Yeah! @borkdude if clj-kondo sees defn -main
in a namespace that doesn't have (:gen-class)
in the ns
form, that could be a useful warning! 🙂
although you can still invoke this with -M -m foo
as well without having to have :gen-class
necessarily - any other heuristics that should point at :gen-class
?
I'm refactoring some code that uses a dynamic db connection built using mount, it looks like
(ns service.test-fixtures
(:require [service.db :refer [*db*]])) ;;the dynamic var
(defn db-tx-rollback-fixture [f]
(jdbc/with-db-transaction [tx *db*]
(jdbc/db-set-rollback-only! tx)
(with-redefs [*db* tx]
(f))))
this code has been copy pasted in numerous repos and i wanted to pull out a bunch of test fictures we have into a common lib. Refactoring this as simply
(defn db-tx-rollback-fixture [db]
(fn [f]
(jdbc/with-db-transaction [tx db]
(jdbc/db-set-rollback-only! tx)
(with-redefs [db tx]
(f)))))
and calling with
(ns service.test-fixtures
(:require [service.db :refer [*db*]]))
(use-fixtures :each (db-tx-rollback-fixture *db*))
obviously doesnt work, I'm trying to wrap my head around how i can write a macro to solve this.Instead of with-redefs
, use binding
. *db*
is dynamic.
how to generate uuid from string ?
Are you fairly new to Clojure @U02DQ45FQF9? If so, maybe ask Qs in #beginners where folks have opted in to helping in depth with basic questions like this.
(logged an issue about gen-class + -main here: https://github.com/clj-kondo/clj-kondo/issues/1417)