Fork me on GitHub
Eric Ihli02:07:47

(defn foo []
  (s/def ::baz string?))
(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

Eric Ihli02:07:55

So I can't clear out all the specs in my namespace with something like

(let [k (keys (s/registry))
        my-k (filter #(= (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

Eric Ihli02:07:14

Aye that's where I was about to head, to calling def-impl.


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 - 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") ))

           (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.

Tamizhvendan S11:07:54

You can wrap it inside a function and pass the kvStore as an argument like below

Tamizhvendan S11:07:59

(defn instance [kvStore]
  (reify Processor
   (init [this ctx]
     ((fn [ctx]
        (println "Processor Initialized: " ctx)
        (reset! kvStore (.getStateStore ctx "user-store")))
   (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.

Alex Miller (Clojure team)12:07:29

You could do the same with a defrecord which has fields (and a consistent type)


I think i found a hint that exposes it as an atom..


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 and failing due to db-spec HikariDataSource (HikariPool-1) is missing a required parameter

José Javier Blanco Rivero20:01:00

Hello Adam! Did you find a solution? I am running into the same issue.

José Javier Blanco Rivero14:01:19

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:


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
(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


this is an extremely common mistake, making me think the app behavior is broken


i need to learn how java actually works 😄


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


Thanks, I'll take a look


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
               (map user-record->map (.getValues page)))
             (.getNextPage page))
^ 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?


using lazy-seqs with side effects / external resources is messy

👍 3

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.

👍 3

will search, thanks Sean!


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)

👍 3

calling concat on concat without yet forching the result, leads to a massive call stack before any work happens

😮 3

this is great. thanks team!


(Stuart's whole Do's/Don't series is good reading, BTW @stopachka)

❤️ 3

> So we have a stack overflow. But why? We used recur. Our code has no stack-consuming recursion. Or does it? (cue ominous music) xD love the writing. Will look deeper