It’s great that you’re learning Clojure, and while it may seem just weird now, stick with it, and soon it’ll become second nature…
First things first, if you are at the REPL, you have several ways of figuring what functions do, the first one being to run them… So in the case of
identity, you could try doing
(identity 1) or
(identity "foo"), maybe. The name is a bit of a giveaway, too.
Also, being at the REPL you can do
(doc identity), which in this case prints out:
Returns its argument.
The second thing you should do, is to properly format the code, which makes it much easier to read:
(defn chop-chop [coll]
(let [x (partition-by identity coll)]
(map (comp str first) x)
(map count x))))
You were quite spot on with your analysis so far.
partition-by splits a collection using a function, and separates the groups when the value returned by that function changes. When you pass
identity to it, it will group by elements that are equal.
x will look like this:
(partition-by identity "aaaabbbcca")
;; => ((\a \a \a \a) (\b \b \b) (\c \c) (\a))
Those are sequences of characters, which is not quite what you’re after, but it gets you almost there.
The next line is a it confusing, but we can separate it into parts to better understand it.
comp composes functions, so basically it gives you a new function that first applies
first to its argument, and then
str to the result of
first. You are mapping that function over your
x, so that will give you a list of single letter strings, one for each group in the result of
partition-by. We can see what this looks like:
(map (comp str first)))
;; => ("a" "b" "c" "a")
map can take several collections, so we should look at what the second collection looks like:
;; => (4 3 2 1)
So now, you are mapping
list over two collections, one containing the single letter strings, and one containing the count of each group in the partitioned list:
;; => ((“a” 4) (“b” 3) (“c” 2) (“a” 1))
And there you have the result you were after. (IIRC, the original problem statement for this asked for a vector, so you can wrap that result in
vec to get:
(vec (chop-chop "aaaabbbcca"))
;; => [("a" 4) ("b" 3) ("c" 2) ("a" 1)]
Hope that clarifies a bit what’s going on
Remember to use the REPL to experiment and get information on those functions you don’t know yet. Also, you can use https://clojuredocs.org to get the documentation enriched with a bunch of examples. It is a great resource.