This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-07-24
Channels
- # aleph (3)
- # beginners (17)
- # boot (8)
- # cider (61)
- # cljdoc (13)
- # cljs-dev (2)
- # clojure (66)
- # clojure-boston (1)
- # clojure-italy (4)
- # clojure-nl (7)
- # clojure-russia (7)
- # clojure-spec (19)
- # clojure-uk (80)
- # clojurescript (73)
- # core-async (4)
- # cursive (6)
- # data-science (1)
- # datomic (33)
- # docs (13)
- # emacs (17)
- # figwheel-main (28)
- # fulcro (12)
- # graphql (1)
- # jobs (3)
- # leiningen (4)
- # luminus (1)
- # off-topic (1)
- # parinfer (1)
- # pedestal (46)
- # protorepl (3)
- # re-frame (30)
- # reagent (47)
- # reitit (10)
- # ring (1)
- # shadow-cljs (94)
- # spacemacs (12)
- # specter (16)
- # tools-deps (6)
- # uncomplicate (1)
- # vim (9)
Im writing some pretty imperative selenium code and the nested lets are getting annoying
any let binding can refer to bindings before it, and it's normal to use _ as a binding name for things done for side effects
@emccue so you rarely need nested lets
user=> (let [a 1 _ (println a) b 3 _ (println (- b a))] (+ a b))
1
2
4
_ is just a name, but it's agreed to mean "I need to bind this but don't use it"
so you can also use it with function args if your function is called by something that passes args you never need etc.
id used it other places in my code like a (with-open [_ (DriverManager/getConnection url)] (println (<< "Created ~{filename}"))
to create a sqlite db
Why are you using low-level JDBC stuff like that? You were asking about clojure.java.jdbc
the other day -- did the documentation I pointed you to not help?
(not meaning to sound accusing, just surprised to see that low-level Java interop stuff)
i'm surprised to see with-open
used like this. won't it need a var to call close
on at the end of its scope?
it uses the value directly - otherwise shadowing would cause bugs
_ doesn't mean "throw away this value", it's just an idiomatic name for a thing you don't use despite needing to bind it
i guess i hadn't thought about it before. yeah i was thinking _
has a good chance of being shadowed repeatedly
right, but the with-open macro is immune to shadowing if you look at the source or expand it
I am trying HTTP Kit but my changes are not showing until I restart the server. How do I develop this way 😮
a common trick is to either use a lib like stuartsierra/component
that lets you reload your http server in a repl with short turnaround time or defining #'app
as your handler that you pass to the http server, so that when you redefine app in the repl it instantly uses the new value
the issue is that if you call (long-running-thing foo)
and long-running-thing
repeatedly uses foo, how can it see new values? it turns out that #'foo
is a var reference, so if foo was defined with defn, it will be a container that is updated when you redefine foo
but regardless of which solution you choose, definitely do something that leaves a repl open so you can redefine things without restarting clojure
Thanks @noisesmith. I will try that.
often your template already passes the app (or maybe handler) with a var quote, so all you really need is to evaluate the new defn and it just works
@somedude314 there's a remarkable set of tricks we use to keep clojure running as we redefine things, the cool thing is most of them actually require us to write higher quality code to work properly :D
@noisesmith: I see. I am trying to apply the above 🙂
Anyone have any ideas why with-redefs
doesn’t want to redef gensym
inside a map-indexed
?
;; Fails: gensym redef ignored
(let [db {:qualifications ["foo" "bar"]}]
(with-redefs [gensym (constantly "id")]
(map-indexed
#(vector %1 {:id (gensym) :text %2})
(:qualifications db))))
;; Fails as above (using fn instead of #() doesn't seem to change anything?)
(let [db {:qualifications ["foo" "bar"]}]
(with-redefs [gensym (constantly "id")]
(map-indexed
(fn [idx v]
(vector idx {:id (gensym) :text v}))
(:qualifications db))))
;; Success: Only works in the inner-most scope?
(let [db {:qualifications ["foo" "bar"]}]
(map-indexed
#(with-redefs [gensym (constantly "id")]
(vector %1 {:id (gensym) :text %2}))
(:qualifications db)))
I’d like to redef gensym
for testing but it’s being a painthis is crazy interesting
user>
(with-redefs [gensym (constantly "redef")]
(->> (map (fn [_] {:id (gensym)})
(range 4))
(filter (fn [{:keys [id]}] (= id "redef")))
#_count))
()
user>
(with-redefs [gensym (constantly "redef")]
(->> (map (fn [_] {:id (gensym)})
(range 4))
(filter (fn [{:keys [id]}] (= id "redef")))
count))
4
@dpsutton You are a legend; that just made the penny drop. It’s because map/map-indexed returns a lazy-seq which means the redef is never being realised properly. If you realise it - like with vec
it works:
(let [db {:qualifications ["foo" "bar"]}]
(with-redefs [gensym (constantly "id")]
;; Realise the seq here
(vec
(map-indexed
(fn [idx v]
(vector idx {:id (gensym) :text v}))
(:qualifications db)))))
I’ve been mapping too long it seems xD Maybe I should start napping - or hammocking? - instead
Anyone got ideas about how to do the transformation in perform
and all-of
better?
(def healthchecks
{:db db-healthcheck
:zipkin zipkin-healthcheck})
(defn- healthcheck-result [check]
(try
(let [res (check)]
(if res
[:success res]
[:failure res]))
(catch Exception e
[:failure (.getMessage e)])))
(defn- all-of [flag result]
{flag (vec (sort (map (fn [[n]] n) (filter (fn [[_ [x]]] (= flag x)) result))))})
(defn- perform [healthcheck-map]
;; {:name1 function2 :name2 function2 :name3 function3} ->
;; [[name1 [:success result1]] [name2 [:failure result2]] [name3 [:success result3]]] ->
;; {:success [name1 name3] :failure [name3]}
(let [checks (map (fn [[name function]] [name (healthcheck-result function)]) healthcheck-map)]
(conj (all-of :success checks) (all-of :failure checks))))
;; (perform healthchecks)
It "works" but it feels super clunky
I feel like there's a transpose of some sort that could be done
(defn perform [healthcheck-map]
(->> healthcheck-map
(map (fn [[name function]]
[name (healthcheck-result function)]))
(group-by second)
(map (fn [[k vs]]
[k (mapv first vs)]))
(into {})))
Awesome, getting there thanks.
https://dev.clojure.org/display/community/Library+Coding+Standards > Don't use a special notation for constants; everything is assumed a constant unless specified otherwise.
I do tend to use ALL-CAPS
for arbitrary parameterized variables. It’s true that all def’s are global constants, but not all symbols are global defs. I find it helps readability to distinguish.
I’ve adopted the +this-is-a-constant+
notation of late and think I prefer it to my previous Java style screaming snake case def
’d constants.
instead of (def IMMUTABLE_THING 42)
how about (def ᵐᵘᵗᵃᵇˡᵉ⁻ᵗʰᶦⁿᵍ (atom 42))
maybe this should have been a twitter :poop: -post instead of a comment here...
OK but alter-var-root is a thing, as is def...
I mean, what is the nuance of meaning meant to be conveyed there, I ask because def means constant to me, so I wonder what hair is intended to be split between using def and using def plus a special name
Any idea why the live reloading is working for me with Compojure but not with bidi: https://bpaste.net/show/b0389b041e6d
@somedude314 remember when we talked about using var quote / passing the var in?
@noisesmith: Aha, adding that made it work! Thanks.
to be fair someone else caught it first this time, but yeah, np
https://dev.clojure.org/display/community/Library+Coding+Standards > Don't use a special notation for constants; everything is assumed a constant unless specified otherwise.