beginners 2026-07-15

Hello Clojurians, I've not used Clojure for a while and now I'm writing a small app that needs to interact with some REST APIs. What's a good way to do this? Currently I have 2 very different ways to use the APIs: one's a .net SDK that gives me rich objects, the other is using raw web requests. So I guess I'm looking for a happy medium

Hello! A kinda similar situation is with AWS API. AWS does have a rich Java SDK (way, way too rich for almost anyone's taste here, I'd wager) and it's also possible to query its APIs directly. Cognitect has come up with https://github.com/cognitect-labs/aws-api and it seems to hit that sweet spot. No incredibly complex SDK bits but also no need to compose all the bits yourself. Source code that you can actually read and follow in one go. So maybe you could do something similar for the API that you have.

👍 1

Thanks, I will take a look

At work, we interact with a lot of (REST-ish) APIs, and we use the hato library for raw HTTP requests with a little bit of domain-specific code wrapped around it for each API. We've found that working with the underlying HTTP calls to be much easier in many cases than trying to use any OO SDKs that vendors provide, since those SDKs assume you're working in an object-based, mutable-data environment—plain HTTP is much more like immutable data: map in, map out.

😲 1

there is also clojure clr, if that helps you at all

Am I missing something or are the swap! forms on line 2 and 18 wrong in this example? I'm trying to get it to work in the REPL and I can't. I feel like they are missing an assoc .

(defn shuffle-titles [store titles]
  (swap! store :idx 0)
  (js/setInterval
   (fn []
     (swap! store
      (fn [state]
        (let [idx (mod (inc (:idx state)) (count titles))]
          (assoc state
                 :title (nth titles idx)
                 :idx idx)))))
   2000))

(defscene name
  :params (atom {})
  :on-mount (fn [store]
              (let [titles ["I am the first title"
                            "It is time for the second title"]]
                (swap! store :timer (shuffle-titles store titles))))
  :on-unmount (fn [store]
                (js/clearInterval (:timer @store)))
  [store]
  [:h1 (:title @store)])
At first I thought it was a clever use of keywords-as-functions, but I don't see how that makes sense here. From Portfolio docs: https://github.com/cjohansen/portfolio/blob/main/docs/portfolio/defscene.md

the second is wrong, but the first at least scans fine at first look

My understanding is that the first one will always swap nil into the atom. What are you seeing that I am not seeing?

(swap! a b c) does (b @a c)

Maybe you missed the first one. There are three swap!s. The first one is (swap! store :idx 0).

so the first (swap! store (fn ...)) does ((fn ...) store)

so the first and third are for sure wrong

Yeah, typo confirmed, then.

Just a thought: could I/would it be a good idea to combine the new :select feature with a bare (s/keys) in order to validate subsets of an entity?

Could you elaborate on what you mean here?

Using (s/keys) without any :req or :opt keys will still validate any keys in the map that have specs associated. If you :select down a map to exactly the keys you expect (say a subset of a "person" entity that only has a name and email instead of more stuff, as per Maybe Not), then could you use the aforementioned behaviour of (s/keys) to simulate the spec2 notion of selecting down a spec?

Oh, you mean checking it with s/valid? and a "generic" Spec that is just (s/keys)?

That's true of all maps tho', right?

(and would work only for qualified keys in your selected map—which I assume is a given)

Yeah, sorry. Meant using s/valid? with s/keys. By selecting out, you're sure that you're only validating the keys you care about. I guess the likelihood of having things in the input map you don't actually want to validate is pretty slim

That would mean you're using spec'ed keys with incorrect values

Alex Miller (Clojure team) 2026-07-15T22:10:22.874799Z

more to come on spec-related integration

5