Thursday, May 22, 2014

Clojure Koans Answers and Explanations - 8 - Higher Order Functions

Let's look at the solutions for the next of Clojure Koans - Higher order functions.
List of all previous solutions is here.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;1
(= [__ __ __] (map (fn [x] (* 4 x)) [1 2 3])
; the way to start reading such expressions is to
; figure out what the anonymous function does.
; from there see what arguments are being passed
; Here map function is used to apply an anon
; to a vector [ 1 2 3].
; The anon multiplies the element by 4
(= [4 8 12] (map (fn [x] (* 4 x)) [1 2 3]))
  
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;2
(= [1 4 9 16 25] (map (fn [x] __) [1 2 3 4 5]))
; pretty similar to the koan #1
; here we need to find out what the anonymous
; function must do
; If the function squares each element, we are good
(= [1 4 9 16 25] (map (fn [x] (* x x)) [1 2 3 4 5]))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;3
(= __ (map nil? [:a :b nil :c :d]))
; Here nil? will be applied to each element of the vector
; only one element is nil
; So, the result vector must be
; [false false true false false]
(= [false false true false false] (map nil? [:a :b nil :c :d]))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;4
(= __ (filter (fn [x] false) '(:anything :goes :here)))
; We saw applying the map function in above examples
; This one is about filter
; which does exactly what it's name suggests
; Here it applies an anonymous function to each
; element of list and selects the element in teh result
; if and only if a true is returned
; Since the function returns false immaterial of argument
; we are bound to get an empty list in the result
(= () (filter (fn [x] false) '(:anything :goes :here)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;5
(= __ (filter (fn [x] true) '(:anything :goes :here)))
; Opposite of the previous
(= '(:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;6
(= [10 20 30] (filter (fn [x] __) [10 20 30 40 50 60 70 80]))
; We need to find some commonality either among the elements
; that are selected. Or we can chose to look at higher level.
; (More on this later)
(= [10 20 30] (filter (fn [x] (< x 40)) [10 20 30 40 50 60 70 80]))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;7
(= [10 20 30] (map (fn [x] __) (filter (fn [x] __) [1 2 3 4 5 6 7 8])))
; In real life map and filter and reduce go hand in hand
(= [10 20 30] (map (fn [x] (* x 10)) (filter (fn [x] (< x 4)) [1 2 3 4 5 6 7 8])))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;8
(= __ (reduce (fn [a b] (* a b)) [1 2 3 4]))
; Reduce is the same reduce made popular
; by hadoop
(= 24 (reduce (fn [a b] (* a b)) [1 2 3 4]))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;9
(= 2400 (reduce (fn [a b] (* a b)) __ [1 2 3 4]))
; one possible solution
(= 2400 (reduce (fn [a b] (* a b)) (cons 100 [1 2 3 4])))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;10
(= "longest" (reduce (fn [a b]
                         (if (< __ __) b a))
                       ["which" "word" "is" "longest"])))
; somewhat convoluted. see one possible solution
(= "longest" (reduce (fn [a b]
                         (if (< (count a ) (count b))  b a))

                       ["which" "word" "is" "longest"]))




1 comment:

  1. I think the point of 9 is to show that you can have a value as well as a collection for reduce: https://clojuredocs.org/clojure.core/reduce.

    ReplyDelete