2
\$\begingroup\$

The purpose of the following code is to, given a vector, compute the two accumulators: 1. head-till-nth element, 2. (n+1)th element-till-last (where n, and this is the catch, iterates from 1 till length-of-list, inclusive).

(let [my-list [1 2 3 4 5 4 3 2 6]]
  (loop [elem 0]
    (when (<= elem (count my-list))
      (do        (println (reduce + (take elem my-list)))
                 (println (reduce + (drop elem my-list)))
                 (recur (inc elem))))))

While this code gets the job done, it is not functional but rather imperative (using a local, elem, as a running index and comparing against the vector's length to determine termination).

I considered using doseq but I can see no immediate way to incrementally slice the vector per the requirements. Using for is also wrong as I'm not trying to create a list comprehension.

I'd appreciate any answer showing the idiomatic Clojure way of doing this.

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

To code in a more functional style, break it down starting with the smallest pieces. I would do it like this:

(defn head-accum [n coll]
  (reduce + (take n coll)))

(defn tail-accum [n coll]
  (reduce + (drop n coll)))

(defn pair-accum [n coll]
  [ (head-accum n coll)
    (tail-accum n coll) ] )

(defn all-pair-accum [coll]
  (let [n-vals (count coll) ]
    (for [split-val (range 1 n-vals) ]
      (pair-accum split-val coll))))

(println (all-pair-accum (range 11)))

;=> ([0 55] [1 54] [3 52] [6 49] [10 45] [15 40] [21 34] [28 27] [36 19] [45 10])
\$\endgroup\$
1
  • \$\begingroup\$ Great. Thank you! Nice seeing how you COULD (and did) use for comprehension. \$\endgroup\$
    – user52901
    Commented Jun 17, 2015 at 2:34
0
\$\begingroup\$

Well, not much of an improvement, but at least this way we let the sequence determine when the loop ends and not some imperative comparison against the sequence's lenght.
(Also got rid of the explicit let when loop implements it implicitly).

(loop [i 1 vtr [1 2 3 4 5 4 3 2 0]]
  (when (seq (drop (- i 1) vtr))
    (reduce + (take i vtr))
    (reduce + (drop i vtr))
    (recur (inc i) vtr)))
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.