This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-14
Channels
- # announcements (10)
- # babashka (14)
- # beginners (51)
- # calva (2)
- # cider (28)
- # cljs-dev (1)
- # cljsrn (3)
- # clojure (185)
- # clojure-dev (15)
- # clojure-europe (6)
- # clojure-italy (2)
- # clojure-nl (6)
- # clojure-uk (45)
- # clojurescript (4)
- # conjure (12)
- # datomic (37)
- # duct (37)
- # figwheel-main (15)
- # helix (23)
- # interceptors (1)
- # jobs (1)
- # jobs-discuss (11)
- # jvm (5)
- # luminus (3)
- # malli (15)
- # off-topic (69)
- # pathom (8)
- # pedestal (2)
- # re-frame (7)
- # reagent (58)
- # reitit (33)
- # remote-jobs (1)
- # rum (14)
- # sci (7)
- # shadow-cljs (15)
- # spacemacs (9)
- # testing (19)
- # timbre (3)
- # tools-deps (14)
(defn foo []
(s/def ::baz string?))
(foo)
(s/valid? ::baz "baz")
(defn fii [k]
(s/def k string?))
(fii ::faa)
(s/valid? ::faa "buzz")
The second example doesn't work. It can't find spec ::faa
. I understand this is because s/def
is a macro and it's creating a spec for the symbol k
rather than the keyword that the symbol evaluates to. How can I change the code so that s/def
gets the value passed in rather than the symbol k
?Macros are "contagious" - anything that constructs parameters to a macro must itself be a macro.
So in this case try defining (defmacro fii ...
to construct the call to s/def
So I can't clear out all the specs in my namespace with something like
(let [k (keys (s/registry))
my-k (filter #(= (namespace %) "com.my.namespace") k)]
(map (fn [x] (s/def x nil)) my-k))
Alternatively, macroexpand or look up the definition of s/def
- you'll find that it forwards to a function def-impl
which you might be able to call directly
yup, the docstring warns "do not call directly" but it can't hurt in your case (which I assume is a dev-time utility)
Seeing s/def
inside another form just freaks me out -- You wouldn't put a regular def
or defn
inside another function!
Hi everyone! Very new to clojure and im am trying to figure out how I can implement a java interface and some new additional fields to the class. For example - https://kafka.apache.org/0110/documentation/streams/developer-guide#streams_processor_process
How would i declare kvStore
so its accessible on this
.
(reify Processor
(init [this ctx]
((fn [ctx]
(println "Processor Initialized: " ctx)
(set! (.kvStore this) (.getStateStore ctx "user-store") ))
ctx))
(process [this k v]
((fn [key value]
(println "Processing Message: " key value)
(println "The Store: " (.kvStore this))
(KeyValue. key value))
k v))
(close [_]
((fn []
(println "Closing"))
)))
I basically need to add a new instance field member to the class.. not sure how to do this.
You can wrap it inside a function and pass the kvStore as an argument like below
(defn instance [kvStore]
(reify Processor
(init [this ctx]
((fn [ctx]
(println "Processor Initialized: " ctx)
(reset! kvStore (.getStateStore ctx "user-store")))
ctx))
(process [this k v]
((fn [key value]
(println "Processing Message: " key value)
(println "The Store: " @kvStore)
(KeyValue. key value))
k v))
(close [_]
((fn []
(println "Closing"))))))
(let [state (atom {:foo "bar"})
x (instance state)]
;do something with the x or state
)
Thanks, this is basically what i ended up with. I was searching for a while though looking for a way to actually create a class with new field members... i can now see how this is a nice clojure alternative to how java does it.
You could do the same with a defrecord which has fields (and a consistent type)
Thanks @U064X3EF3 just found your post 🙂 https://puredanger.github.io/tech.puredanger.com/2010/11/23/implementing-java-interfaces-with-clojure-records/
10 years later... :)
Does anyone have any experience plugging a database pooling library like Hikari into hugsql? I'm calling my hugsql fucntion like so
(db/insert-account db/datasource {:password "password" :email ""})
where datasource is a HikariDataSource object internally hugsql seems to be calling get-connection
in clojure.java.jbdc and failing due to db-spec HikariDataSource (HikariPool-1) is missing a required parameter
Hello Adam! Did you find a solution? I am running into the same issue.
I solved this! I didn't paid enough attention to this in the jdbc documentation about connection pooling: "Authentication credentials must use :username
(if you are using c3p0 or regular, non-pooled, connections, then the db-spec hash map must contain :user
)." source: https://cljdoc.org/d/com.github.seancorfield/next.jdbc/1.3.847/doc/getting-started#connection-pooling
Can someone help me build a project with lein? I have a new project made with
lein new app test-foo
Then I do:
cd test-foo
lein uberjar
Compiling test-foo.core
Created /home/stuart/Source/clojure/test-foo/target/uberjar/test-foo-0.1.0-SNAPSHOT.jar
Created /home/stuart/Source/clojure/test-foo/target/uberjar/test-foo-0.1.0-SNAPSHOT-standalone.jar
(base) stuart@stuart-Z87M-D3H:~/Source/clojure/test-foo$ java target.uberjar.test-foo-0.1.0-SNAPSHOT.jar
Error: Could not find or load main class target.uberjar.test-foo-0.1.0-SNAPSHOT.jar
I can't resolve this could not find or load main class error ???
My core.clj looks like
(ns test-foo.core
(:gen-class))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "Hello, World!"))
I haven't changed it from lein creating it.
My project file:
(defproject test-foo "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url ""
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url " "}
:dependencies [[org.clojure/clojure "1.10.1"]]
:main ^:skip-aot test-foo.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
OK, I realise my mistake, I need to do
java -jar target/uberjar/test-foo-0.1.0-SNAPSHOT.standalone.jar
ughthis is an extremely common mistake, making me think the app behavior is broken
it makes sense to create the jar as a subtask of making the uberjar, but leaving it there to be used instead of the uberjar is a design flaw
do you know any good tutorials for using graalvm to make a native binary from my uberjar? So i get a quicker start up time?
I don't recommend this as a beginner task
there are a lot of things within clojure you can't use, or have to use differently, in order to make that work
if you want an easy way to have graalvm and fast startup from the beginning, you could use babashka
though
it doesn't support all of clojure, but neither does graalvm, and it did a bunch of the hard stuff for you
Hey team, I'd love to turn this -> into a lazy sequence
(defn get-all-users []
(loop [ret []
page (-> (FirebaseAuth/getInstance)
(.listUsers nil))]
(if page
(recur (concat
ret
(map user-record->map (.getValues page)))
(.getNextPage page))
ret)))
^ firebase gives me a paginating api for users.
I'd love to give an all-users
lazy sequence, which only fetches when required.
This way, I can do something like:
(->> (get-all-users)
(pmap do-some-work))
---
I haven't quite wrapped my head around lazy-seq
. Am not sure how I can express the statement: keep giving values i have. if i don't, try to paginate to the next page
How could I go about writing this?that said, the get-all-users could turn into something like (mapcat :values (iterate (fn [{:keys [page]} (let [nxt (.getNextPage page)] {:page nxt :values (.getValues nxt)}) ...)
There's a new function under consideration for Clojure 1.11 which makes it easier to iterate over side-effecting things that produce data in pages -- you could use the code from the Jira issue until that lands.
the big problem with the code you have now is a stack of concats that could blow up
concat and imperative looping don't mix nicely
oo (mapcat :values (iterate (fn [{:keys [page]} (let [nxt (.getNextPage page)] {:page nxt :values (.getValues nxt)}) ...)
looks great! Thanks team.
Noob q: mind expounding on stack of concats that could blow up
? What do you mean? (if blow up stack frame, i thought loop
avoided that)
(I think that blog post covers it)
Yup, it even gives the loop
/`concat` example to show the problem...
@stopachka I recommend the blog post but the tl;dr version is that a lazy-seq (the thing you are trying to understand here), works by turning "next" into a thunk (cached function of zero arguments)
calling concat on concat without yet forching the result, leads to a massive call stack before any work happens