add avg and juxt

This commit is contained in:
Christophe Grand 2015-09-03 14:25:19 +02:00
parent 5d20db6ba3
commit e576631ca4
2 changed files with 34 additions and 3 deletions

View file

@ -41,7 +41,11 @@ Add this dependency to your project:
Execution time mean : 20,604297 µs
```
`avg` is a reducing fn to compute the arithmetic mean. `juxt` is used to compute several reducing fns at once.
```clj
=> (into {} (x/by-key odd? (x/reduce (x/juxt + x/avg))) (range 256))
{0 [16256 127], 1 [16384 128]}
```
## License

View file

@ -1,7 +1,7 @@
(ns net.cgrand.xforms
"Extra transducers for Clojure"
{:author "Christophe Grand"}
(:refer-clojure :exclude [reduce for partition str])
(:refer-clojure :exclude [reduce for partition str juxt])
(:require [clojure.core :as clj]))
(defmacro for
@ -27,7 +27,8 @@
([~acc ~binding] ~body)))))
(defn reduce
"A transducer that reduces a collection to a 1-item collection consisting of only the reduced result."
"A transducer that reduces a collection to a 1-item collection consisting of only the reduced result.
Unlike reduce but like transduce it does call the completing arity (1) of the reducing fn."
([f]
(fn [rf]
(let [vacc (volatile! (f))]
@ -88,5 +89,31 @@
(vswap! m assoc! k noprf))
(unreduced acc))))))))
(defn avg
"Reducing fn to compute the arithmetic mean."
([]
(let [count (volatile! 0)
sum (volatile! 0)]
(fn secret-container
([] (when (pos? @count) (/ @sum @count)))
([n]
(vswap! count inc)
(vswap! sum + n)
secret-container))))
([acc] (acc))
([acc x] (acc x)))
(defn juxt
"Returns a reducing fn which compute all rfns at once and whose final return
value is a vector of the final return values of each rfns."
[& rfns]
(let [rfns (vec rfns)]
(fn
([] (mapv #(vector % (volatile! (%))) rfns))
([acc] (mapv (fn [[rf vacc]] (rf (unreduced @vacc))) acc))
([acc x]
(let [some-unreduced (reduce (fn [some-unreduced [rf vacc]]
(when-not (reduced? @vacc) (vswap! vacc rf x) true))
false acc)]
(if some-unreduced acc (reduced acc)))))))