DEV Community

Discussion on: Daily Challenge #249 - Incremental Changes

Collapse
 
not_jffrydsr profile image
@nobody • Edited

Clojure - Level 2 🌟🌟

(ns dailyChallenge.IncrementalChange249
  (^:level2))

;; recursive function w/ tail-end optimization
(defn algo [number, step, iterations]
  {:pre (>= iterations 1)}
    (let [accum 
            (loop [ result [number] itr iterations]
              (if (= 1 itr)
                (conj result step)
                (recur result (dec itr))))]
       (apply + accum))


(deftest test-algo
  (is (= 52 (algo 2 5 10))
  (is (= 35 (algo 17, 3, 6)))

(run-tests 'test-algo)
Collapse
 
quoll profile image
Paula Gearon

Compared to your "level 1", this is more like the question asked, since it asks for an algorithm rather than the answer. (I totally agree that it should be (+ number (* step iterations))).

In Clojure it's usually better to preference core functions, followed by reduce, followed by loop/recur.

The clojure.core function approach is just:

(defn algo
 [number step iterations]
 (->> number
      (iterate (partial + step))
      (drop iterations)
      first))

But that's really using iterate to do the algorithm part. So reduce might be more in the spirit of things. It's shorter too 🙂

(defn algo
 [number step iterations]
 (->> (repeat step)
      (take iterations)
      (reduce + number)))
Collapse
 
not_jffrydsr profile image
@nobody • Edited

Awesome breakdown! Thanks Paula. 🙏🏿

I feel like you're right on the hierarchy of abstraction to use for Clojure functions (there's just so many, and many of them are composed)._

I could've just used pure-recursion without loop/recur but I don't get the power of the AST's tail-end optimizer for loops. Thank you for reminding me of the thread-macro.