-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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