This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-22
Channels
- # adventofcode (37)
- # beginners (74)
- # boot (2)
- # boot-dev (31)
- # cider (88)
- # clara (109)
- # cljs-dev (63)
- # clojure (96)
- # clojure-argentina (1)
- # clojure-czech (1)
- # clojure-dusseldorf (2)
- # clojure-france (2)
- # clojure-germany (3)
- # clojure-greece (2)
- # clojure-italy (5)
- # clojure-norway (1)
- # clojure-spain (1)
- # clojure-spec (25)
- # clojure-uk (46)
- # clojurescript (26)
- # cursive (19)
- # data-science (5)
- # docs (2)
- # duct (18)
- # editors (2)
- # emacs (3)
- # figwheel (2)
- # fulcro (29)
- # graphql (3)
- # hoplon (143)
- # juxt (7)
- # klipse (1)
- # leiningen (5)
- # lumo (1)
- # monads (1)
- # off-topic (23)
- # onyx (49)
- # powderkeg (6)
- # re-frame (4)
- # reagent (8)
- # ring (3)
- # shadow-cljs (24)
- # specter (70)
- # sql (1)
- # unrepl (96)
- # yada (3)
when you see code like this
(defn mmap [m f a] (->> m (f a) (into (empty m))))
(defn complete-all [v] (swap! todos mmap map #(assoc-in % [1 :done] v)))
(defn clear-done [] (swap! todos mmap remove #(get-in % [1 :done])))
how do folks figure out what’s going on? There are at least 3 places where arguments are getting moved around here (`swap!`, the anonymous function, and the threading macro) and I am having a hard time following. is there a trick to tackling stuff like this?for what it is worth, the specific thing that I can’t figure out is that “1” in the assoc-in
and get-in
which seems like they would only be operative on one element in the provided sorted-map
@lee.justin.m I think that code could be written in a much clearer way. As for the 1
, you'll need to look at the data structure that's being used to how the todos -- based on the code above, I'd expect each todo to be a vector who's second element is a hash map that has an element done
(a Boolean).
A vector is associative on its indices, so (get [:a :b :c] 1)
is :b
Hi. I've been using clojure for ~1year. Recently did an overview of clojurescript presentation at the local javascript meetup. One thing that was really strange is that people associate functional programming with haskell aka monads, category theory, pattern matching. etc.. Just wondering is it wrong if I say something like to me functional programming in clojure seems more similar to javascript (except for: implicit returns , laziness & immutability). than to haskell, elm & ocaml
?
Still a bit of a beginner, might be missing some things. But really don't see FP in clojure as being hard, or something to be afraid of...
I now and then encounter functions named with a trailing *
in other peoples sourcecode.
Is this a common naming convention? What exactly does it mean? Is there some documentation somewhere?
@U3WJG25EV These are "Earmuffss used to denote dynamic vars: https://clojure.org/guides/weird_characters#__code_var_name_code_earmuffs
Ah, I see. In clojure.core, these often denote special forms (e.g. fn*
, let*
). I'm not sure about other meanings, though.
The single *
at the end of a function name is a common convention used when you’re writing a function that’s only used by a macro or another function. For example, I might write foo
that does something to a collection of records, but each individual record has some complicated processing to go through, so I pull out a foo*
function that does the heavy lifting.
For coders like me who are too lazy to think up a better name for foo*
😉
hello,is this the idiomatic way of iterating over a collection and modifying any stack abstraction in Clojure?
@diginomad without more information it's hard to say for sure, but from what you've posted I'd likely look at reduce
what that code shows is exactly what reduce does - at each step you have a new accumulated value (called s here) and you do something with the nth item of the collection
in fact as written, that is identical to (reduce f stack collection)
(ignoring the ... at least)
is there a way to start a repl with some installed packages without creating a project?
Could install https://github.com/pallet/alembic, then install and load needed libraries in REPL
If you’re ok using CLJS instead of CLJ, you could check out planck or lumo
or lein-try
: https://github.com/rkneufeld/lein-try
Is writing command-line applications with Clojure a thing?
@sayammasood You could do this too. It's in https://clojure.org/guides/deps_and_cli
I mean, something like this but for Clojure:
@sayammasood, I think @ghsgd2’s comment was in regards to the REPL question. As for your question, yes, CLI’s in Clojure is absolutely a thing! What you’re looking for is tools.cli
https://github.com/clojure/tools.cli
Thanks @admay! Will definitely take a look.
I have a bunch of pairs [a b] and I would like to know the smallest b for each a. What would be an idiomatic way of doing this in clojure?
E.g., if I start with [[0 0] [0 1] [1 1] [1 2] [1 3] [2 2]], I would like to get {0 0 1 1 2 2]
@sabbatical2017 my first inclination is to start with (group-by first ...)
, then use sort or min to get the smallest b out of each a key
but it could all be done in one go using a reduce instead
something like (reduce (fn [smalls [a b]] (update smalls a (fnil min b) b)) {} ...)
I guess there's a few tricks in that which might be unfamiliar given this is #beginners, but feel free to ask for clarification
min-key
might help
@noisesmith @alexmiller Thank you very much! I verified that (reduce (fn [smalls [a b]] (update smalls a (fnil min b) b)) {} ...)
works but it does not look too idiomatic to me as it looks very different from what I am trying to accomplish.
E.g., in datomic there is functionality where you can say something along the lines of :first (min :second)
which will automatically do this.
IMHO that reduce looks exactly like the thing you are trying to accomplish, and reduce is idiomatic
then again datomic never clicked for me - I did a workshop with Stuart Sierra even and it just never made sense
FTR I also looked at min-key
but was not able to contort it into a reasonable-looking working solution.
My best shot at this is (map-vals #(apply min (map second %)) (group-by first x))
Where I defined (defn map-vals [f m] (make-map (keys m) (map f (vals m))))
and (defn make-map [ks vs] (apply array-map (map vector ks vs)))
I tested that make-map
and map-vals
work
And, for the record I have (def x [[0 0] [0 1] [1 1] [1 2] [1 3] [2 2]])
You probably want to use Specter for stuff like that, if possible. https://github.com/nathanmarz/specter
But when I run that first form (with the x
in it), I get CompilerException java.lang.IllegalArgumentException: No value supplied for key: [2 2],
@sabbatical2017 the idiomatic version of make-map is (into {} x)
oh wait you are splitting so (into {} (map vector x y))
@noisesmith Yes, thank you, (defn make-map [ks vs] (into {} (map vector ks vs)))
definitely looks nicer! It also fixes the IllegalArgumentException
.
oh wait - that's zipmap
- a builtin
@flowthing Thank you! I was also wondering about specter, but thought I'd try with plain Clojure first. Do you know enough specter to write down an idiomatic specter solution to this to compare?
@noisesmith Thanks, that's great! I thought that make-map
looked like something that would be provided! I also thought that about map-values
BTW 🙂
there's a few versions of map-vals, I like (into {} (map (fn [[k v]] [k (f v)])) coll)
(note that map is called with just one arg there)
thread-last macro arguably makes group-by solution cleaner
(def pairs [[0 0] [0 1] [1 1] [1 2] [1 3] [2 2]])
(->> pairs
(group-by first)
(map (fn [[k keyvals]]
[k (apply min (map second keyvals))]))
(into {}))
also the map / fn combo can be an arg to into, it doesn't need to be executed separately
@sabbatical2017: I'm definitely not particularly well-versed with Specter, but (specter/transform [specter/ALL] (partial apply min) [[0 0] [0 1] [1 1] [1 2] [1 3] [2 2]])
yields [0 0 1 1 1 2]
.
isn't that just taking the min of each pair?
I know the whole map-vals
and map-keys
thing is controversial but does anyone know why they aren’t in clojure.core
?
Well, I can't immediately come up with anything that's an improvement over the existing solutions.
@admay https://dev.clojure.org/jira/browse/CLJ-1959 has some discussion on the topic.
@flowthing I found that PR and that’s what made me curious. Alex said in his first response, “Rich will have his own opinion regardless.” That’s what I was most curious about
There was also this Reddit thread a while back: https://www.reddit.com/r/Clojure/comments/7coeu6/on_why_clojure_doesnt_have_mapvals_on_simplicity/