posted an update

Along with learning #clojure, I'm still working toward thinking like a functional programmer. This includes grasping the concepts and knowing the tools. It helps to get something working in the more-familiar imperative style - then figure out a better - more functional - solution.

For example, Problem 30: Compress a Sequence on 4clojure requires the programmer to remove consecutive duplicates from a sequence. So vector [1 1 2 3 3 2 2 3] should become a sequence '(1 2 3 2 3) and the string "Leeeeeerrroyyy" would be "Leroy" (when reassembled as a string). My first attempt simple built up new sequence while perform an "if/else" check: only add the next item to the new sequence if the last item doesn't match. This can be done with a reducing function, like so:

(reduce (fn [coll val] (if (some #{val} coll) coll (conj coll val))) [] (seq "Leeeeeerrroyyy"))
# => \L \e \r \o \y

Kind of boring. I then found a much cooler (!), i.e., functional, approach. The partition-by function allows the programmer to split up a sequence based on the result of some other function while retaining the order. This would be like taking a line of school children and asking them to pair up with the person to their left and/or right if they were wearing the same color. Turns out, in #clojure, you can partition by identity (if the values are equal). This would return a list of lists:

(partition-by identity [1 1 2 3 3 2 2 3])
# => ((1 1) (2) (3 3) (2 2) (3))

Not quite the full solution, but what we have done is provided a intermediate sequence that can be converted into the solution by mapping over the result simply taking the first item of each sub-list:

(map first (partition-by identity [1 1 2 3 3 2 2 3]))
# => (1 2 3 2 3)

No "if/else" statements, uses built-in functions, much more elegant!

Log in or sign up for Devpost to join the conversation.