This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-02-27
Channels
- # beginners (113)
- # calva (39)
- # cider (18)
- # cljs-dev (19)
- # cljsrn (1)
- # clojure (80)
- # clojure-dusseldorf (1)
- # clojure-finland (1)
- # clojure-gamedev (1)
- # clojure-germany (2)
- # clojure-italy (38)
- # clojure-nl (16)
- # clojure-spec (90)
- # clojure-uk (81)
- # clojurescript (28)
- # clojutre (9)
- # cursive (47)
- # data-science (4)
- # datomic (21)
- # emacs (1)
- # events (2)
- # fulcro (11)
- # graphql (2)
- # hoplon (8)
- # hyperfiddle (23)
- # jobs (2)
- # kaocha (4)
- # lein-figwheel (1)
- # luminus (1)
- # mount (1)
- # off-topic (41)
- # pathom (5)
- # pedestal (27)
- # reitit (6)
- # remote-jobs (7)
- # ring-swagger (6)
- # shadow-cljs (42)
- # spacemacs (1)
- # sql (9)
- # tools-deps (6)
- # uncomplicate (2)
- # vim (5)
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."
Would anyone help me to understanding the parameter form inside the fn
? (The code snippet comes from: https://github.com/chrishowejones/blog-film-ratings/blob/master/src/film_ratings/handler/index.clj
(defmethod ig/init-key :film-ratings.handler/index [_ _]
(fn [{[_] :ataraxy/result}]
[::response/ok (views.index/list-options)]))
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)
42
user=> (let [{[x] :ataraxy/result} {:a 1 :ataraxy/result []}] x)
nil
user=> (let [{[x] :ataraxy/result} {:a 1 :ataraxy/result nil}] x)
nil
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
user=>
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)
nil
user=>
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: https://clojure.org/guides/destructuring . 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
https://clojure.org/guides/destructuring#_associative_destructuring 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 https://clojure.org/guides/destructuring#_where_to_destructure -- and includes an example very much like the function above that you asked about.
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.
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?
Perhaps thereās no strong purpose in this example but I found another one actually uses the destructured data: https://github.com/chrishowejones/blog-film-ratings/blob/master/src/film_ratings/handler/film.clj#L13
BTW I was walking through this tutorial: https://circleci.com/blog/build-a-clojure-web-app-using-duct/
Nice this looks like a good resource for me
Thanks
@dawranliou Yeah, and that function has :as request
but then doesn't use request
so that's also a bit odd.
Indeed thatās a bit more oddity there again š
Welcome
@seancorfield i reflexively add :as req
to my handlers when i start writing them and often forget to delete it later
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).
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
I've always been confused by the preference for a memoized 0-arg function over using delay
which is made for specifically this purpose...
(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...)
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))
42
user=> (force 42)
42
(force xmldoc)
would also work
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
(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)
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))
map is lazy, but you would need to call force or deref on original
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
People of Clojure Land, have ever anyone here deployed an Uberwar and connected to the REPL?
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
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
?You are saying here that you expect a map consisting of keys lat
and long
and you wish to call this map treasure-location
you are right, the order doesn't matter, the :keys destructure is based on the keys themselves
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
oh thats really cool, didnāt know
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?
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
Yeah, you can be explicit: (let [{my-a-key :a} {:a 12}] ...)
, is useful for renaming
: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)
Yeah there is, you can use ::keys
for the current namespace or require/as a namespace and then use ::alias/keys
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.
(Not that I want to, but for complete understanding!)
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?
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
but yes