Skip to content

Instantly share code, notes, and snippets.

@tsdh
Forked from kohyama/example-to-use-r-reduce.clj
Created June 11, 2012 06:44
Show Gist options
  • Save tsdh/2908767 to your computer and use it in GitHub Desktop.
Save tsdh/2908767 to your computer and use it in GitHub Desktop.
R-reduce is an variant of reduce-right which accepts a condition to stop. In Clojure.
; Using this 'r-reduce',
; you can write calculations having same structure
; as 'take', 'drop', 'take-while', 'drop-while', 'fold-right' and 'reduce-right'
; without writing loops explicitly.
(use 'clojure.test)
; Accumulate what calculations should be done into acc.
; When stopping reversing acc and apply it.
(defn r-reduce [init updt pred retn f coll]
(loop [stat init [h & r :as curr] coll acc (list identity)]
(if (or (pred stat) (nil? r))
((apply comp* acc) (retn curr))
(recur (updt stat) r (cons (partial f h) acc)))))
(defn fold-right [f z coll]
(r-reduce coll next nil? (fn [x] (f (first x) z)) f coll))
(defn reduce-right [f coll]
(r-reduce coll next nil? first f coll))
(defn r-reduce-old [init updt pred retn f coll]
(loop [stat init [h & r :as curr] coll acc (vector identity)]
(if (or (pred stat) (nil? r))
((apply comp acc) (retn curr))
(recur (updt stat) r (conj acc (partial f h))))))
(defn reduce-right-old [f coll]
(r-reduce-old coll next nil? first f coll))
(defn my-take [n coll]
(r-reduce 0 inc #(<= n %) (fn [x] '()) cons coll))
(defn my-drop [n coll]
(r-reduce 0 inc #(<= n %) identity (fn [x y] y) coll))
(defn my-take-while [p coll]
(r-reduce coll next #(not (p (first %))) (fn [x] '()) cons coll))
(defn my-drop-while [p coll]
(r-reduce coll next #(not (p (first %))) identity (fn [x y] y) coll))
(defn my-reverse [coll]
(r-reduce coll next nil? #(list (first %)) #(concat %2 (list %)) coll))
(deftest test-reduce-rights
(are [expected result] (= expected result)
(fold-right - 2 '(3 1 4 1 5 9)) 3
(reduce-right - '(3 1 4 1 5 9 2)) 3
(my-take 5 '(3 1 4 1 5 9 2)) '(3 1 4 1 5)
(my-drop 5 '(3 1 4 1 5 9 2)) '(9 2)
(my-take-while odd? '(3 1 4 1 5 9 2)) '(3 1)
(my-drop-while odd? '(3 1 4 1 5 9 2)) '(4 1 5 9 2)
(my-reverse '(3 1 4 1 5 9 2)) '(2 9 5 1 4 1 3)))
; comp and partial version
(defn prtl-r-reduce [init updt pred retn f coll]
(loop [stat init [h & r :as curr] coll cont identity]
(if (or (pred stat) (nil? r))
(cont (retn curr))
(recur (updt stat) r (comp cont (partial f h))))))
; comp version
(defn comp-r-reduce [init updt pred retn f coll]
(loop [stat init [h & r :as curr] coll cont identity]
(if (or (pred stat) (nil? r))
(cont (retn curr))
(recur (updt stat) r (comp cont #(f h %))))))
; nested functions version
(defn nstd-r-reduce [init updt pred retn f coll]
(loop [stat init [h & r :as curr] coll cont identity]
(if (or (pred stat) (nil? r))
(cont (retn curr))
(recur (updt stat) r #(cont (f h %))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment