Fork me on GitHub

I see a lot of posts here about http-kit but looking at github it seems like the project is not being maintained


Is there another library I should be using if I am just getting started? Or is it just stable


@mitchell_clojure A lot of Clojure libraries are very stable and can look "unmaintained".


It's common for a Clojure library to be very focused on a specific problem-to-solve so it's possible for a Clojure library to be "done".


That said, http-kit looks pretty well-maintained to me, with 2.4.0 Alpha 3 coming out about a month ago. We use it heavily at work, if that helps you feel more comfortable about using it? 🙂


Thanks Sean, your input is always appreciated. Looks like you are right about that, I just think I put a little too much stake into this blurb on the github: "http-kit's author (@shenfeng) unfortunately hasn't had much time to maintain http-kit recently. To help out I'll be doing basic issue triage, accepting minor/obvious PRs, etc."

Daw-Ran Liou03:02:03

Would anyone help me to understanding the parameter form inside the fn? (The code snippet comes from:

(defmethod ig/init-key :film-ratings.handler/index [_ _]
  (fn [{[_] :ataraxy/result}]
    [::response/ok (views.index/list-options)]))

Daw-Ran Liou04:02:43

I feel like it’s doing some kind of parameter destruction but I can’t make sense of the map: {[_] :ataraxy/result}


@dawranliou That is destructuring that will match {:ataraxy/result [...]} with zero or more elements where ... is


user=> (let [{[x] :ataraxy/result} {:a 1 :ataraxy/result [42]}] x)
user=> (let [{[x] :ataraxy/result} {:a 1 :ataraxy/result []}] x)
user=> (let [{[x] :ataraxy/result} {:a 1 :ataraxy/result nil}] x)
user=> (let [{[x] :ataraxy/result} {:a 1 :ataraxy/result :stuff}] x)
Execution error (UnsupportedOperationException) at user/eval158 (REPL:1).
nth not supported on this type: Keyword


See how the value of that key can be nil or have zero or more elements -- but cannot be certain types of values. In this case tho', the _ is just a placeholder so this function is really ignoring the values anyway and so it's just "documentation" really...


In particular, the element doesn't have to exist at all

user=> (let [{[x] :ataraxy/result} {:a 1}] x)

Daw-Ran Liou04:02:10

Thanks @mitchell_clojure and @seancorfield. I wasn’t aware of this way of destructuring. Those were great explanations


It's actually a combination of both sequential and associative destructuring, explained more thoroughly here: . It doesn't smell idiomatic to me to try to hint at the structure of your data in this way, though, but I /am/ just a beginner

seancorfield04:02:04 shows the {x :k} style first, and then the {:keys [k]} form -- the former can bind values to symbols that don't match the keys, whereas the latter requires your names match your keys.


The last example in this section shows everything together -- and includes an example very much like the function above that you asked about.

Daw-Ran Liou04:02:04

I was also looking at the links you two mentioned. I think I am more used to seeing the {:keys [k]} form than the associative destructuring. Now I learn something new.


Yeah, the :keys form is by far the most common. Good to know about :syms and :strs as well.

👍 5

What I don't really get is the purpose of destructuring in this specific example if you are not going to use the contents of said collection anyways. Is it really just trying to be more "clear" about what we want the argument to be?

Daw-Ran Liou04:02:04

Perhaps there’s no strong purpose in this example but I found another one actually uses the destructured data:


Nice this looks like a good resource for me


@dawranliou Yeah, and that function has :as request but then doesn't use request so that's also a bit odd.

Daw-Ran Liou04:02:38

Indeed that’s a bit more oddity there again 😛


@seancorfield i reflexively add :as req to my handlers when i start writing them and often forget to delete it later

Alex Miller (Clojure team)15:02:28

I find those :as can serve as useful docs even if they aren't used


yeah, put readable names on all the things (see also (fn foo [] ...) on anonymous functions - it even makes stack traces more readable)


i started unanonimizing my functions when i saw babel doing it in js and realized >stacktrace


@vale Yes, I can definitely see value in it -- if it is done consistently (which it is not in that tutorial, unfortunately).


o/ silly question, I’m trying to figure out why something I wrote is slow


I’m looking at docs online, and there’s this:

;; Now lets parse the XML into a Document.  It is not strictly
;; necessary to memoize, but this provides a cache of the parsed
;; document which will make operations on the document faster.
(def xmldoc
     (memoize (fn [] (xml->doc (hackernews-rss-xml)))))


why is there a memoize? wouldn’t (def xmldoc (xml->doc "contents of the url")) do the same thing?


(provided I’m happy to load the contents into memory at the time of execution rather than delay)


yeah, pretty much


memoizing an arity 0 function seems very strange to me


it should be a delay


it is to avoid side effects at code load


I've always been confused by the preference for a memoized 0-arg function over using delay which is made for specifically this purpose...


ah. i see. thanks


(even at work, if I use delay people ask "what's that I don't get it", then they jump through hoops with memoize and forcing things to be 0 arg functions for the same semantics...)

😞 5

helpful trick: force on any object that isn't a delay acts as identity, on a delay it accesses the value of the realized delay - it makes it straightforward to make a function that accepts a delay or a regular value


so would that normally be written (def xmldoc (delay (xml->doc "contents of the url"))) and then resolved with @xmldoc, right?


user=> (force (delay 42))
user=> (force 42)


a lot of stuff in the code you linked is weird junk


(force xmldoc) would also work


how would you debug why your code is slow?


my guess it is written by someone also just learning clojure, which is fine, but hardly an example to follow


@lady3janepl I would use a profiler, sadly there's a learning curve to translate the info from a profiler to useful improvements to clojure code


lots of weird forcing seqs to be vectors, before treating them as seqs again


(tdlr: I have an xml, I use this lib to parse it, I then map a function over a collection of nodes and turn them into nil-or-map)


…turns out that compiling an expression beforehand helps. Thanks 😄


another q with regards to delays: if I create a delay, and then want to map over it (but also stored as a delay), do I have to do this: (def further (delay (map f @original))) or is it sufficient to: (def further (map f original))


(how smart is map?)


map is lazy, but you would need to call force or deref on original


thanks 🙂


also, if xml->doc were lazy, you could leverage that instead of using a delay


also, there's often good reason to use lazy values inside a limited scope rather than the top level, because that way you avoid holding the whole thing in memory (might not be a concern here)


yeah, I’d normally go with something like that, but I have a file that fits in memory and I’m essentially writing a script to clean/extract data and dump it back into json


so it needs to be processed in one go anyway


I’m asking questions so that I know how to use it in future, basically 😄


People of Clojure Land, have ever anyone here deployed an Uberwar and connected to the REPL?


what "the repl"?


may be the nRepl I guess ?


are you running an nrepl server?


I did a deploy of my pedestal Uberwar, then connected to the repl port, my guess it's nRepl


now, the first strange thing, the Clojure's version at the console is different from my lein's projec.clj version


it shows 1.7.0 and over my project.clj is 1.10.0


you should check what jars are in your war, and check lein :version


is it expected to not be able to enter the name spaces?


can we sort maps by keywords alphabetically?


this is what sorted-map and sorted-map-by are for, as long as all keys are sortable with one another


(for a normal clojure map, the types of the keys are unrestricted, and you can't sort many combinations of types...)


Understanding destructurings seems to be one of the sticking points for me. In something like this:

(defn receive-treasure-location
  [{:keys [lat lng] :as treasure-location}]
  (println (str "Treasure lat: " lat))
  (println (str "Treasure lng: " lng))
So the map notation tells me it's going to be destructuring a map right? You use the same notation as the collection you expect? Then :keys means pull out all the keys and associate them with what? Is this automatically going to make lat the first key and lng the second key? But maps are unordered? And then :as means the whole map will still be bound as treasure-location?

Lennart Buit21:02:06

You are saying here that you expect a map consisting of keys lat and long and you wish to call this map treasure-location


so you expect the map will only have two keys?


you are right, the order doesn't matter, the :keys destructure is based on the keys themselves


it isn't ordered at all

Lennart Buit21:02:10

there is no expectency, if there is a key :lat in the map, it will be bound to lat in your function, otherwise its nil


{:keys [lat lng]} binds (get ... :lat) to lat and (get ... :lng) to lng


but the keywords in the map used for that example are :lng and :lat not lng and lat


there is also :syms and :strs for other types of keys

Lennart Buit21:02:39

oh thats really cool, didn’t know


what does :syms stand for?

Lennart Buit21:02:15

symbols I’d assume


and :keys/:syms/:strs are just sugar on the general destructuring syntax, where the key can be any kind of literal


user=> (let [{:strs [c d] :keys [a b] :syms [e f]} {:a 1 :b 2 :c 3 :d 5 :e 6 :f 7 "a" 8 "b" 9 "c" 10 "d" 11 "e" 12 "f" 13 'a 14 'b 15 'c 16 'd 17 'e 18 'f 19}] [a b c d e f])
[1 2 10 11 18 19]


it might even be easier to understand starting from the general destructuring form and understanding that, then looking at :keys as sugar on top of that, instead of trying to understand :keys in isolation


so in your destructuring part you don't use the : notation for the actual keys you just leave that out?


it is implicit


ok, ok. seems obvious i guess but I don't think a single tutorial has told my dumb butt that


it is implicit, the destructuring code understands that :keys [a b] means you want to lookup the keys :a and :b in the map and bind the values to the locals a and b


where as :syms [a b] means look up the symbols a and b in the map and bind the values to the locals a and b


the general destructuring syntax for maps is kind of the map inverted


{a :a} means look up the keys :a and bind the value found to the local a

Lennart Buit21:02:42

Yeah, you can be explicit: (let [{my-a-key :a} {:a 12}] ...), is useful for renaming


user=> ((fn [{a #inst "2008"}] a) {#inst "2008" 1})


:keys, :syms, and :strs are special cases (I think these days there is some additional stuff for namespaced keys which I haven't used yet)

Lennart Buit21:02:12

Yeah there is, you can use ::keys for the current namespace or require/as a namespace and then use ::alias/keys

Lennart Buit21:02:50

May I ask for my understading, these binding forms, are they “fixed”, or is it possible to define a new “shorthand” like :keys, :syms or :strs, for example :lowercase-strs or something strange like that.

Lennart Buit21:02:11

(Not that I want to, but for complete understanding!)

Lennart Buit21:02:06

Cool, so thats a no


thanks, folks. unrelated question: When reading other people's code I see idx used a lot. What idiom is that pertaining too?

Lennart Buit21:02:41

sounds like index?


seems right. of course now looking at my notes for questions to eventually ask i didn't write an example so can't remember how it was used. i'm sure the context should have told me.


like when I see acc I'm starting to learn that means they are using this let binding for their accumulator


more often it would be a function arg in reduce, or a loop binding