
æè¿ã
ãã©ã³ã¹ãã¥ãŒãµãŒã¯å声ãåŸãŸãã-Clojure 1.7ã®æ°æ©èœã§ããŸã ãªãªãŒã¹ãããŠããŸããã å·çæç¹ã§ã¯ãClojure 1.7-alpha5ãé¢é£ããŠããŸããã
Python ã
Ruby ã
JavaScript ã
PHP ã
Java ã
C ++ ã
Lua ã
Erlangãªã©ã®ããŸããŸãªèšèªã§ããªãã®æ°ã®ãã©ã³ã¹ãã¥ãŒãµãŒããŒããæ¢ã«ç»å ŽããŠããŸãã ãããŠ...ããã¯å°ããã£ããã§ãã çµå±ãããªãåã«ïŒClojure 1.5ã«æ»ã£ãŠïŒã
reducersã©ã€ãã©ãªã
远å ãããŸãã ãã ããã
ãªãã¥ãŒãµãŒã«ã€ããŠã¯èª°ã話ãããäœãç§»æ€ããŸããã§ããã
Clojureã§ããããã¹ãŠã®æžéæ©ãšãã©ã³ã¹ãã¥ãŒãµãŒãå¿
èŠã ã£ãçç±ãèŠãŠã¿ãŸãããïŒæ¬åœã«å¿
èŠãªã®ã§ããããïŒïŒãããããã©ã®ããã«æ©èœããã©ã®ããã«äœ¿çšããã®ã...
ãã®èšèªã®ã³ã³ããã¹ãå€ã§Clojureã«ç±æ¥ããæŠå¿µãèšè¿°ããã®ã¯ééã£ãŠããŸãã ãããã£ãŠãClojureã«ã¯å€ãã®ãªã¹ãããããŸãã ãããããã¿ã³ã¯ââãããŸããã äžè¬ã«ãClojureã®åæç¥èïŒç¹ã«
ã·ãŒã±ã³ã¹ã®æŠå¿µïŒã¯é©åã§ãããHaskellãç¥ãå¿
èŠã¯ãããŸããã ãŸãããªã¹ããããŠããæšæºé¢æ°ã®ãªã¹ãã¯ãã¹ãŠå®éã«ã¯éåžžã«å€æŽãããŠãããæã«ã¯ããããã«ãå£ããŠããããšãäºåã«èŠåããŸãã ç°¡çŽ åã®ããã«ãã¹ãŠã ãããããåçã¯åã
ããªããŒã§ãã
ãªãã«ããŸã...
ãã®ãããClojureã¯é¢æ°åèšèªã§ããã€ãŸãã
éåžžã® åœä»€å ãµã€ã¯ã«ã¯è¯ã
ãããŸããã
ããŠã倧äžå€«ãç§ãã¡ã¯æ¬åœã«æãã§ããŸããã§ãã-æ©èœ
çã«æ¥œããéå
ããããŸãïŒ
(defn my-reduce ([rf coll] ;; (if-let [s (seq coll)] (my-reduce rf (first s) (next s)) (rf))) ([rf acc coll] (if-let [[x & xs] (seq coll)] (recur rf (rf acc x) xs) acc)))
å®éã«ã¯ã
reduce
ã¯ãã¡ããã
å°ãç°ãªãæ¹æ³ã§å®è£
ãããŸãããä»ã¯éèŠã§ã¯ãããŸãããå¿ããŠã¯ãããŸããã
rf
颿°ïŒreduct颿°ãšåŒã³ãŸãããïŒã¯ãããã§2ã€ã®åŒæ°ãåããŸããæåã®åŒæ°ã¯ãäžçš®ã®ãç§»åç¶æ
ãã§ãã 2çªç®ã¯
coll
ã·ãŒã±ã³ã¹ã®èŠçŽ ã§ãã åæç¶æ
ãæå®ãããŠããªãå Žåã
(first coll)
ãŸãã¯
(rf)
ãŸãã ç¶æ
acc
ãããã©ãã°ãããªããã
rf
ãšåŒã¶åèŠçŽ ã«ã€ããŠãã³ã¬ã¯ã·ã§ã³
coll
å
šäœã
acc
ãŸãã èŠçŽ ã宿ãããã
acc
è¿ããŸãã
å°ããªäŸã æååã®ãªã¹ããããããããã®åèšã®é·ããèšç®ãããšããŸãã
ã«ãŒãã䜿çšããåœä»€ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
(defn length-of-strings [strings] (with-local-vars [acc 0] ;; -, Clojure ! (doseq [c strings] (var-set acc (+ @acc (count c)))) ;; @acc))
ã«ãŒãç¶æ
ã¯ãåçŽãª
acc
ïŒæ°å€ïŒã«ãŠã³ã¿ãŒã§ãã åå埩ã§ã
(+ @acc (count c))
ã«çããèšå®ããŸãã
ãããŠãã1åã
reduce
ã®ã¿ã
reduce
ãŸãã
(defn length-of-strings [coll] (my-reduce (fn ([acc c] (+ acc (count c)))) ;; - 0 ;; coll))
äžæçã«æ lazããå¿ãããå Žåã
map
ã
filter
ãªã©ã®å€ãã®ããªããã£ããªæäœãå®è£
ã§ã
filter
ã
(defn my-map [f coll] (my-reduce (fn [acc c] (conj acc (fc))) [] coll)) (defn my-filter [p coll] (my-reduce (fn [acc c] (if (pc) (conj acc c) acc)) [] coll))
take
ãå®è£
take
æå®
reduce
ãã
reduce
ãªãã·ã§ã³ã¯æ©èœããªããªããŸã-ãµã€ã¯ã«ã¯åžžã«ã·ãŒã±ã³ã¹å
šäœãå®è¡ããŸãïŒããã¯ããã¹ãŠãé
å»¶ããŠããHaskellã®äžçš®ã§ã¯ãããŸããïŒã
ãã®æ¬ ç¹ãå
æããããã«ãããŒãžã§ã³1.5ã§ã¯ç¹å¥ãª
æŸèæããŒã«ãŒã远å ãã察å¿ããè¿°èªã
reduced?
ã åæã«ã
reduce
ãæžãçŽããæ¬¡ã®ãããªãã®ãåŸãŸããïŒ
(defn my-reduce ([rf coll] (if-let [s (seq coll)] (my-reduce rf (first s) (next s)) (rf))) ([rf acc coll] (if-let [[x & xs] (seq coll)] (let [ret (rf acc x)] (if (reduced? ret) @ret (recur rf ret xs))) acc)))
reduct颿°ãè¿ããããš
(reduced ...)
ãã«ãŒããäžæããå€
@ret
ãŸãã
(defn take-r [n coll] (my-reduce (fn [[n1 acc] c] (if (pos? n1) [(dec n1) (conj acc c)] (reduced acc))) [n []] coll)) ;; ! (take-r 5 (range)) ;; => [0 1 2 3 4]
çŽ æŽããã
åæžæ©èœãæãåºããã«ã¯ããããŸããã æ¬è³ªçã«ãããã¯
reduce
é¡äŒŒç©ã§ãããæåŸã ãã§ãªã
acc
ãã¹ãŠã®äžéå€ã®
é
å»¶ãªã¹ãã®ã¿ãè¿ããŸãã ãããã°æã«äœ¿çšãããšéåžžã«äŸ¿å©ã§ãã ã¢ã«ãŽãªãºã ã¹ãããã颿°ãšããŠèšè¿°ããå
¥åããŒã¿ã
reduce
ããŠã³ã¬ã¯ã·ã§ã³ã«å¯ŸããŠ
reduce
ãå®è¡ããŸãã äœããééã£ãŠããå Žåã¯ã
reduce
ã
reductions
ã«çœ®ãæããREPLã§å®è¡ãããã¹ãŠã®äžéã¹ããããååŸããŸãã ãµã€ã¯ã«ã§ã¯ãããã»ã©ç°¡åã§ã¯ãããŸãã-ãããã°æŸèæãä¿®æ£ããå¿
èŠããããŸãããããã¯ããŸã䟿å©ã§ã¯ãããŸããã
åæžã¯ããèªäœã§æçšã§ããå¯èœæ§ããããŸã;éä¹ã¯èšç®ããããã«ãããŸãïŒ
;; => ** (def factorials (reductions *' (cons 1 (map inc (range))))) (nth factorials 20) ;; => 2432902008176640000
Clojureã¯
ã·ãŒã±ã³ã¹ã䜿çšããŠã³ã¬ã¯ã·ã§ã³ã埪ç°ããŸãã ãã¯ãã«ãããã·ã¥ããŒãã«ããŸãã¯åçŽãªã€ãã¬ãŒã¿ã調ã¹ãå Žåã倧éã®äžæãªããžã§ã¯ããããŒãå
ã«äœæãããŸãã
ãã®ãããªç¶æ³ã§èŠæ±ãããæãããªæé©åã¯ããããçã«ããªã£ãŠããã³ã¬ã¯ã·ã§ã³ã«å¯ŸããŠç¹å¥ãª
reduce
ãªãã·ã§ã³ãå®è£
ããããšã§ãã ã³ã¬ã¯ã·ã§ã³ããã®ãããªæé©åã«åœ¹ç«ããªãå Žåã¯ãèšäºã®åé ã§ç€ºãããã®ãšåæ§ã®æšæºå®è£
ã䜿çšããŠãã ããã ãããè¡ãã«ã¯ãç¹å¥ãªãããã³ã«
clojure.core.protocol / CollReduceããããŸãã ã³ã¬ã¯ã·ã§ã³ãªããžã§ã¯ãããµããŒãããå Žåããã®å®è£
ã¯
clojure.core/reduce
å
ã§äœ¿çšãããŸãã ãããã£ãŠãClojureã®
reduce
ã¯éåžžãåæ§ã®
doseq
ã«ãŒããããé«éã§ãã
å€å§åš
ãã©ã³ã¹ãã©ãŒããŒã¯ã1ã€ã®ãªãã¯ã颿°ãåããæ°ãããªãã¯ã颿°ãè¿ã颿°ã§ãã
ããšãã°ãã1ãã€å¢å ããããã©ã³ã¹ãã©ãŒããŒã次ã«ç€ºããŸãã
(defn inc-t [rf] (fn [acc c] (rf acc (inc c)))) ;; (reduce + 0 (map inc [1 2 3 4])) ;; => 14 (reduce (inc-t +) 0 [1 2 3 4]) ;; => 14
ãã®åé¡ãå€å°äžè¬åããŠã
inc
代ããã«é¢æ°ãæå®ããããšãã§ããŸãã
(defn map-t [f] (fn [rf] (fn [acc c] (rf acc (fc))))) (def inc-t (map-t inc)) (def dec-t (map-t dec)) ;; ... (reduce (inc-t +) 0 [1 2 3 4]) ;; => 14
ãããŠãããã§ãäŸãã°ããã©ã³ã¹ãã©ãŒããŒããã£ã«ã¿ãŒãïŒ
(defn filter-t [pred] (fn [rf] (fn [acc c] (if (pred c) (rf acc c) acc)))) (def odd?-t (filter-t odd?)) (def even?-t (filter-t even?)) ;; (reduce (even?-t *) 1 [1 2 3 4]) ;; => 8
è€æ°ã®å€å§åšãçµã¿åãããããšã¯å¯èœã§ããïŒ ãã¡ããïŒ
(defn odd?-inc-t [rf] (odd?-t (inc-t rf))) ;; .. (def odd?-inc-t (comp (filter-t odd?) (map-t inc))) ;; .. (def odd?-inc-t (comp (fn [rf] (fn [acc c] (if (odd? c) (rf acc c) acc))) (fn [rf] (fn [acc c] (rf acc (inc c)))))) ;; (defn odd?-inc-t [rf] (fn [acc c] (if (odd? c) (rf acc (inc c)) acc))) ;; (reduce * 1 (->> [1 2 3 4 5] (filter odd?) (map inc))) ;; => 48 (reduce (odd?-inc-t *) 1 [1 2 3 4 5]) ;; ==> 48
ãã©ã³ã¹ãã©ãŒããŒããéãã®é åºã§é²ãããšã«æ³šæãã䟡å€ããããŸãã ã³ã¬ã¯ã·ã§ã³ã®èŠçŽ ã
B
ã«å°éããåã«ãã©ã³ã¹ãã©ãŒã
A
ã§åŠçãããå Žåã
(comp AB)
ããã«ããããæ¥çããå¿
èŠããããŸãã ãããŠä»ãããªãã¯ïŒ
(def cc (vec (range 1000000))) (time (reduce + 0 (->> cc (filter odd?) (map inc)))) ;; "Elapsed time: 171.390143 msecs" ;; => 250000500000 (time (reduce ((comp (filter-t odd?) (map-t inc)) +) 0 cc)) ;; "Elapsed time: 93.246015 msecs" ;; => 250000500000
æ¹æ³ã¯æ¬¡ã®ãšããã§ããæçœãªéåºŠã®æ¥æ¿ãªå¢å ïŒ ãã¡ããããã¹ãŠã¯å€ãã®è©³çްãšããŸããŸãªãã¥ã¢ã³ã¹ã«äŸåãããããå®éã«ã¯ã²ã€ã³ã¯ç°ãªãå ŽåããããŸãã äžè¬ã«ããã®ã³ãŒãããã³ãããŒã¯ãšããŠäœ¿çšããã¹ãã§ã¯ãªããšèšãããã§ãã
ããããå
šäœãšããŠãçµæã¯é©ãã«ã¯ã»ã©é ãã§ãã
map
ãš
filter
ã䜿çš
map
ãšã2ã€ã®äžéã·ãŒã±ã³ã¹ãäœæãããŸãã å
ã®ãã¯ãã«ãå®è¡ãããã£ã«ã¿ãŒåŠçãããå€ã®äžæçãªãªã¹ããäœæããŸãã æ¬¡ã«ããã®ãªã¹ãã調ã¹ãŠãèŠçŽ ãæ¡å€§ããå¥ã®ãªã¹ããäœæããŸãã ãããŠæåŸã«ãå€ããŸãšããŠããã§ã«èª¬æããŸãã
äžæ¹ããã©ã³ã¹ãã©ãŒããŒã䜿çšãããªãã·ã§ã³ã§ã¯ãäžæçãªã³ã¬ã¯ã·ã§ã³ã¯äœæãããŸããã 代ããã«ã
odd?
ãœãŒã¹èŠçŽ ã«ããã«é©çšãã
odd?
ãããã³
inc
ã
ç§ã®æžéæ©ã¯ã©ãã«ãããŸããïŒ
ãããŠãããŒãžã§ã³1.5ãæ°ããæšæºã©ã€ãã©ãª
clojure.core.reducers
å°å
¥ãããŸã§ããã¹ãŠã¯é 調
clojure.core.reducers
ã ããã§ãã
å¥ã®ã©ã€ãã©ãªãæç€ºçã«ã€ã³ããŒãããå¿
èŠããããŸãã ãŸãã
map
ã
filter
ã
take-while
ãªã©ã®ããŒãžã§ã³ãçºè¡šããŸããã ãããŠããã¡ããããããã¯
clojure.core
éåžžã®ããŒãžã§ã³ãšäºææ§ããããŸããã ãããã£ãŠãåçŽãª
(use 'clojure.core.reducers)
代ããã«
(use 'clojure.core.reducers)
(require '[clojure.core.reducers :as r])
ãšèšè¿°ããæ¹ãé©åã§ãã
ã§ã¯ãæžéæ©ãšã¯äœã§ããïŒ ç°¡åã«èšããšãæããªããšã§ãïŒã¬ãã¥ãŒãµãŒãšã¯ãåæžã§ãããªããžã§ã¯ãã®ããšã§ãã
clojure.core.reducers
芳ç¹ã§ã®ã³ã¬ã¯ã·ã§ã³ã¯ãã¹ãŠã¬ãã¥ãŒãµãŒã§ãã ããã·ã¥ããŒãã«ã¯ã¬ãã¥ãŒãµãŒã§ãã
java.lang.String
ã¬ãã¥ãŒãµãŒã ãŸãããã¡ããã
nil
ã å®çŸ©ãèŠãŠã¿ãŸãããïŒ
(defn reducer [coll xf] ;; `xf` - (reify clojure.core.protocols/CollReduce (coll-reduce [this f1] (let [f2 (xf f1)] (clojure.core.protocols/coll-reduce coll f2 (f2)))) (coll-reduce [this f1 init] (let [f2 (xf f1)] (clojure.core.protocols/coll-reduce coll f2 init)))))
ããã§
coll
ã³ã¬ã¯ã·ã§ã³ãååŸãããæ°ããã³ã¬ã¯ã·ã§ã³ãè¿ãããŸããããã§ã
reduce
ãå®è¡ã§ããŸãã èŠçŽ ã远å ããããåé€ããããèŠçŽ ã調ã¹ããããããšãã§ããŸããã ãã ãã
reduce
éå§ããå
reduce
reduct颿°ã¯
xf
ãã©ã³ã¹ãã©ãŒããŒãééããŸãã
(def nums [1 2 3 4 5]) (def nums+1 (reducer nums inc-t)) (reduce + 0 nums) ;; => 15 (reduce + 0 nums+1) ;; => 20
ãã§ã«è¿°ã¹ãããã«ãreducersã©ã€ãã©ãªã¯ç¬èªã®ãªãã·ã§ã³
map
ã
filter
ã
take-while
ãªã©ãçºè¡šããŠããŸãã ãããã¯ãã¹ãŠæžéæ©ãåãå
¥ãã察å¿ããå€å§åšããåãä»ããããŠãããæ°ããæžéæ©ãè¿ããŸãã
ããã¯
clojure.core.reducers/map
ããã«
clojure.core.reducers/map
ïŒãã¡ãããèŠãç®ã¯å€§ãã
ç°ãªããŸã ïŒã
(def map-r [f coll] (reducer coll (map-t f)))
ãããŠä»ãããããã¹ãŠãã©ã®ããã«äœ¿çšã§ãããã®ããã€ãã®äŸïŒ
(require '[clojure.core.reducers :as r]) (def nums [1 2 3 4 5 6 7 8]) (type (map inc nums)) ;; => clojure.lang.LazySeq (reduce conj [] (map inc nums)) ;; => [2 3 4 5 6 7 8 9] (type (r/map inc nums)) ;; => clojure.core.reducers$folder$reify__1234 ;; - sequence (reduce conj [] (r/map inc nums)) ;; => [2 3 4 5 6 7 8 9] ;; (reduce conj [] (r/filter odd? nums)) ;; => [1 3 5 7] (reduce + 0 (->> nums (r/map inc) (r/map inc))) ;; => 52 ;; ~~ (+ 0 (inc (inc 1)) (inc (inc 2)) ...) (reduce + 0 (->> nums (r/filter odd?) (r/map inc))) ;; => 20 ;; ~~ (+ 0 (inc 1) (inc 3) ...)
å¹³è¡
æ£çŽã«èšããšãããããããªãã¥ãŒãµãŒãã¯ç¡é§ã§ãã ããã©ã«ããã®æ¹ãæ£ããã§ãããã å®éã
CollReduce
ãããã³ã«ïŒã¬ãã¥ãŒãµãŒããããã£ãšåã«ç»å ŽããïŒã«å ããŠãå¥ã®ããéèŠãª
CollFold
ãããã³ã«ãã©ã€ãã©ãªã§å®£èšãããŠããŸãã
(defprotocol CollFold (coll-fold [coll n combinef reducef]))
ååãšããŠãããã¯éåžžã«äŒŒãŠãããéå
颿°ã®ã¿ã2ã€ã«ãªãããããã«ããåŒæ°
n
ã远å ãããŸããã ã¢ã€ãã¢ïŒäžéšã®ã³ã¬ã¯ã·ã§ã³ã¯è€æ°ã®ã¹ã¬ããã§å®è¡ã§ããŸãã ç°¡åã«èª¬æãããšããµã€ãºãçŽ
n
èŠçŽ ã®ãããã¯ã«åå²ããåããŒã¹ã
#(reduce reducef (combinef) %)
ã䜿çšããŠæããããã§ãããçµæãªã¹ãïŒãããã¯ããšã«1ã€ïŒãåã³
#(reduce combinef %)
ãã
#(reduce combinef %)
ãŸãã
䞊è¡ããŠæããããããšãã§ããã¬ãã¥ãŒãµãŒã¯ã
ãã©ã«ããŒãšåŒã°ã
ãŸã ã
CollFold
ãããã³ã«ããµããŒãããŠããã®ã¯ããã¯ã¿ãŒãšããã·ã¥ããŒãã«ã®2ã€ã®æšæºã³ã¬ã¯ã·ã§ã³ã®ã¿ã§ãã
(def v (vec (range 10000000))) ;; , 1 (time (reduce + v)) ;; "Elapsed time: 648.897616 msecs" ;; => 49999995000000 ;; (time (r/coll-fold v 512 + +)) ;; "Elapsed time: 187.414147 msecs" ;; => 49999995000000
ãããçã«ããªã£ãŠãããã¹ãŠã®æšæº
CollFold
å®è£
ã
CollFold
ã ããã¯ãããšãã°ã
r/map
ã
r/filter
ã
r/mapcat
ã
r/flatten
ã§ãã äžæ¹ã
r/take
ã
r/take-while
ã
r/drop
ã¯äžŠååããµããŒãããŠããŸããã äžèšã¯
r/map
å®è£
ã§ããã åœŒå¥³ã®æŽæ°ãããããŒãžã§ã³ã¯æ¬¡ã®ãšããã§ãã
(def map-r [f coll] ;; `reducer` `folder` (folder coll (map-t f)))
coll-fold
çŽæ¥äœ¿çšããå¿
èŠã¯ãããŸãã-æ¥åžžã®ããŒãºã«åããã
æãããã¿ã©ãããŒããããŸãã
n
ã®ããã©ã«ãå€ïŒãããã¯ãµã€ãºïŒã512ã«èšå®ããŸããäžè¬ã«ããã³ãã¯æç¢ºã§ã-ã¬ãã¥ãŒãµãŒã¯ãå€§èŠæš¡ãªã³ã¬ã¯ã·ã§ã³ïŒ> 1Kã¢ã€ãã ïŒã察象ãšããŠããŸãã ãŸãã
coll-fold
çŽæ¥äœ¿çšããªãã§ã
coll-fold
ãåŒã³åºããŸãã
ããããŸã
foldcatããããŸãã äžçš®ã®é«éåïŒãã«ãã¹ã¬ããã«ããïŒãªãã·ã§ã³
#(reduce conj [] %)
ã ãã®é¢æ°
㯠ã
Counted
ã
Sequable
ãããã³
CollFold
ãå®è£
ãã
clojure.core.reducers.Catãªããžã§ã¯ãã
è¿ããŸã ã
(r/map inc [1 2 3]) ;; => #<reducers$folder$reify__..... ;; ** ? ;; .. `reduce` (reduce conj [] (r/map inc [1 2 3])) ;; => [2 3 4] ;; ... (def v (vec (range 1000000))) (time (count (reduce conj [] (r/map inc v)))) ;; "Elapsed time: 90.124397 msecs" ;; => 1000000 ;; - , `foldcat` (time (count (r/foldcat (r/map inc v)))) ;; "Elapsed time: 25.054988 msecs" ;; => 1000000 (time (count (r/foldcat (r/map inc (r/foldcat (r/map inc v)))))) ;; "Elapsed time: 32.054988 msecs" ;; => 1000000 ;; `foldcat`, , foldable (, ) (satisfies? r/CollFold (r/foldcat [])) ;; => true
圌ãã¯ã·ãŒã³ã«çªå
¥ã......
æžéæ©ãšã¯ç°ãªãããã©ã³ã¹ãã¥ãŒãµãŒã¯ç¬ç«ããã©ã€ãã©ãªã§ã¯ãããŸããã
clojure.core
ã¢ãžã¥ãŒã«ã«çŽæ¥çµ±åãããã®ã¯ããããæŠå¿µïŒã¢ã€ãã¢ãèªãã§ãã ããïŒã§ãã ããŒãžã§ã³1.7ã§ãã®æè¿ãåŸ
ã£ãŠããŸãïŒå°ãæ®ã£ãŠããŸãïŒã
ç°¡åã«èª¬æãããšããã©ã³ã¹ãã¥ãŒãµãŒã¯åãååã®ãã©ã³ã¹
ãã©ã³ãã§ããããã©ã³ãå
ã倿ŽãããåŸã«ã®ã¿åå
ã倿ŽãããŸãã ããŠãã»ãšãã©ïŒãããããéå
颿°ã¯0ãš2ã®åŒæ°ã ãã§ãªãã1ãåãããšãã§ããŸãããã©ã³ã¹ãã¥ãŒãµã¯ããããã0-1-2-aryéå
颿°ããæ°ãã0-1-2-aryéå
颿°ãžã®é¢æ°ã§ãã ã
(def typical-transducer (fn [rf] (fn ([] ...) ;; ([acc] ...) ;; ... ([acc c] ...))) ;; , , ;; `map-t`, 33% (defn map-t-improved [f] (fn [rf] (fn ([] (rf)) ;; ([acc] (rf acc)) ;; ([acc c] (rf acc (fc)))))) ;; `c` `(fc)`
åæèŠçŽ ãå¿
èŠãªå Žåã¯ãåè¿°ã®ããã«0é
éå
颿°ãåŒã³åºãããšãã§ããŸãã å®éã2é²ããªã¢ã³ãã¯ãåæžèªäœã«äœ¿çšãããŸãã 1é
ãªãã·ã§ã³ã¯ããžã§ãå
šäœã®æåŸã§ïŒ
reduce
å®äºæã«ïŒåŒã³åºãããŸãã æåŸã®åŸã«æ°ããèŠçŽ ãã远å ãããå¿
èŠãããå Žåã«å¿
èŠã§ãã
äŸïŒã³ã¬ã¯ã·ã§ã³ããã®ç¹°ãè¿ããã¹ããããã
éè€æé€ãã©ã³ã¹ãã¥ãŒãµãŒïŒ
(defn my-dedupe [] (fn [rf] ;; , ! (let [prev (atom ::none)] (fn ;; - ([] (rf)) ([acc] (rf acc)) ([acc c] (let [p @prev] (reset! prev c) (if (= pc) acc (rf acc c)))))))) (def rf ((my-dedupe) +)) (reduce rf 0 [1 1, 2 2, 3, 1 1]) ;; => 7 (reduce rf 0 [1 1, 2 2, 3, 1 1]) ;; => 6 ;; ... `rf` , 2
埮åŠãªç¹ã¯ããã©ã³ã¹ãã¥ãŒãµãŒãæ°ããéå
颿°ãè¿ãããšã§ãã ããã«ããã®éå
颿°ã¯å¯å€ç¶æ
ãæã¡ãå®éã«ã¯3ã€ã®ç°ãªãããšãå®è¡ã§ããŸãïŒã¢ãªãã£ããšã«1ã€ïŒã
ãŸããããçš®ã®ãªããžã§ã¯ãã ãããåæã«ããã©ã³ã¹ãã¥ãŒãµãŒèªäœã«ã¯ç¶æ
ããªããäžçš®ã®å·¥å ŽãšããŠã®ã¿æ©èœããŸãã
reduct颿°ã®1é²ããªã¢ã³ãã®äœ¿çšäŸãšããŠã
partition-allãæå®ãããŠããŸãã ç°¡çŽ åãããå®è£
ïŒ
(defn partition-all-t [n] (fn [rf] (let [buffer (java.util.ArrayList. n)] ;; ! (fn ([] (rf)) ([acc] (if (.isEmpty buffer) ;; - (rf acc) ;; ... (let [v (vec (.toArray buffer)) ;; acc' (rf acc v)] ;; 2- `rf` ;; (rf acc')))) ([acc c] (.add buffer c) (if (= n (.size buffer)) ;; - "" (let [v (vec (.toArray buffer))] (.clear buffer) (rf acc v)) ;; - acc)))))) ;; , ( , (conj) => []) (reduce ((partition-all-t 3) conj) (range 10)) ; >> ClassCastException java.lang.Long cannot be cast to clojure.lang.IPersistentCollection ;; ... ;; , []... (reduce ((partition-all-t 3) conj) [] (range 10)) ;; => [[0 1 2] [3 4 5] [6 7 8]] ;; , ...
ããŒã... 0é
ãªãã·ã§ã³ã1é
ãªãã·ã§ã³
((partition-all-t 3) conj)
ãåŒã³åºãããŸããã§ãã-éåžžã®
reduce
ã¯ãããããã¹ãŠã®é©æ°ã«ã€ããŠäœãç¥ããŸããã ã³ã¬ã¯ã·ã§ã³ã空ã®å Žåã«ã®ã¿0-aryãªãã·ã§ã³ãåŒã³åºãã1-aryãªãã·ã§ã³ã¯ãŸã£ããåŒã³åºããŸããã
ãããã£ãŠã圌ãã¯æ°ãã
transduce
颿°ãäœæããŸããã ããã§ã¯ãã廿¢ãããã
reduce
ãšã¯ç°ãªããåæç¶æ
ãæç€ºçã«èšå®ãããŠããªãéããåžžã«
(rf)
åŒã³åºããŸãã ãããŠããã®é¢æ°ã¯
(rf acc)
ããããŠ
äžåºŠã ãåŒã³åºãããšãä¿èšŒãããŠããŸãã ãããŠã
transduce
èªäœã倿åšãåŒã³åºããå¯å€éå
æ©èœãç®ããé ããŸãã èšãæããã°ããã¹ãŠã®æ±ãäœæ¥ïŒå¯äœçšã®èгç¹ããïŒã¯ãå
éšãã§è¡ãããŸãã
;; , (transduce (partition-all-t 3) conj (range 10)) ;; => [[0 1 2] [3 4 5] [6 7 8] [9]] ;; ... ! ;; ( ) (transduce (comp (filter odd?) (partition-all-t 3)) conj (range 10)) ;; => [[1 3 5] [7 9]]
ãããã
reduce
代ããã«
transduce
ã䜿çšããããšãããšã©ããªããŸããïŒ
(reduce (identity -) 0 [1 2 3 4]) ;; => -10 ;; ~~ (- (- (- (- 0 1) 2) 3) 4) (transduce identity - 0 [1 2 3 4]) ;; => 10 ;; !
reduce
ã
transduce
ã«çŽæ¥çœ®ãæããããšã¯äžå¯èœã§ããããšã倿ããŸãã-1é
éå
颿°ã®æ°ããèŠä»¶ãå¹²æžããŸãã ãã®äŸã§ã¯ãèšç®ãå®äºããåŸãåŒã³åºãã
transduce
(- acc)
ãçµæã®ç¬Šå·ãéã«ããŸãã å®äºãããšãç¶æ³ãä¿®æ£ã§ããŸãã
((completing -) 3 2) ;; => 1 ((identity -) 1) ;; => -1 ((completing -) 1) ;; => 1 (transduce completing - 0 [1 2 3 4]) ;; => -10 ;; !
ãã©ã³ã¹ãã©ãŒããŒããã©ã³ã¹ãã¥ãŒãµãŒãæäœ
ããããã®èšèªã®äžæ žã«ã¯ãç¹å¥ãªæ©èœãç»å ŽããŠããŸãã ãŸãããããã®éåžžã«ãã©ã³ã¹ãã¥ãŒãµãŒã®æšæºã®ã»ããã远å ããããšãæåŸ
ãããŸãã ãããŠãå€ãã®æ°ãã颿°ãçæããªãããã«ïŒããããéåžžã«å€ãããã2ã€ã®ã¢ã«ãŠã³ãã§æ··ä¹±ããŸãïŒãæ¢åã®
map
ã
filter
ã
take
ã
mapcat
ã
mapcat
ããã³companyãã¢ããã°ã¬ãŒãããããšã«ããŸããã
(map inc [1 2 3]) ;; => (2 3 4) (map inc) ;; => #<core$map$fn__4525 clojure.core$map$fn__4525@2d9e9038> ;; ! ;; (transduce (map inc) + [1 2 3]) ;; => 9 (transduce (comp (map inc) (filter even?)) + [1 2 3]) ;; => 6 ;; ~~ (+ (inc 1) (inc 3)) => 6
transduce
å ããŠã
transduce
æäœããããã®æ©èœãããã€ããããŸãã
;; (sequence (map inc) [1 2 3]) ;; => (2 3 4) ;; (transduce (map inc) conj [1 2 3]) ;; => [2 3 4] ;; ... ;; `sequence` ** ! ;; `transduce` (take 5 (sequence (map inc) (range))) ;; => (1 2 3 4 5) ;; `into` (into [9] (map inc) [1 2 3]) ;; => [9 2 3 4]
ããããæãé¢çœãæ©èœã¯
æè²ã§ãã
seq
ãåŒã³åºããŠjava-iteratorã
reduce
ãååŸã§ãããããã·ãªããžã§ã¯ããè¿ããŸãã ãã®ãªããžã§ã¯ãã¯ãåã«
transduce
ãŸãã¯
sequnce
åŒã³åºãããšãæåŸ
ãããŠããŸãã äºçްãªããšã§ããã䟿å©ã§ãã
(def odds (eduction (filter odd?) (range))) (def evens (eduction (remove odd?) (range))) ;; sequential (take 5 odds) ;; => (1 3 5 7 9) ;; sequence 100500 ;; - sequence GC (nth odds 100500) ;; => 2010001 ;; reduce ( LazyCol) ;; ~= (reduce ((filter even?) ((take 100500) +)) 0 (range)) (transduce (take 100500) + evens) ;; => 10100149500
忢ã忢ã忢ã
clojure.core.reducers/reducer
æãããŸãããæå°åããããšããã§ããã
seq
å®è¡
seq
èš±å¯
seq
ããŠããŸããã
r/reducer
ã¯ãŽãç®±ã«æšãŠãŸãïŒ ãããã
r/folder
ã§ã¯ãªãã圌ã¯ãã«ãã¹ã¬ããã®æ¹æ³ãç¥ã£ãŠããŸãïŒ
(require '[clojure.core.reducers :as r]) (def v (vec (range 1000000))) (time (transduce (map inc) + v)) ;; "Elapsed time: 120.193971 msecs" ;; => 500000500000 (time (r/fold + (r/folder v (map inc)))) ;; "Elapsed time: 37.597224 msecs" ;; => 500000500000 ;; ! (transduce (take 100500) + v) ;; => 5050074750 (r/fold + (r/reducer v (take 100500))) ;; => 5050074750 ;; ;; reducer - eduction (r/fold + (eduction (take 100500) v)) ;; => 5050074750 (reduce + (r/folder v (take 100500))) ;; => 5050074750 ;; (r/fold + (r/folder v (take 100500))) ;; => 109071345018 ;; ... ;; ( )
ãã©ã³ã¹ãã¥ãŒãµãŒã䜿çšãããšãéåžžã®
map
/
filter
/
etc
ïŒé
å»¶ã·ãŒã±ã³ã¹ã«åºã¥ãïŒãšæ¯èŒããŠåªããããã©ãŒãã³ã¹ãšãæè»æ§/æœè±¡æ§ã®äž¡æ¹ãå®çŸããŸãã ããã§ã¯ãclojurã·ãŒã±ã³ã¹ã«ã€ããŠèª¬æããŠããããšã«æ³šæããŠãã ãããæœè±¡åãšé床ã®ç¹ã§ã¯ããã©ã³ã¹ãã¥ãŒãµã¯éåžžã®ã€ãã¬ãŒã¿/åæå/ãžã§ãã¬ãŒã¿ã«å¹æµããŸãïŒç°ãªãèšèªã§ã¯ç°ãªãåŒã³æ¹ã§ãïŒã
ããããClojureã«æ»ããŸãã 以åã®
core.asyncã«ã¯ã
map>
ã
map<
ã
filter<
ã
filter>
ãªã©ã®ãããªå€ãã®é¢æ°
ããããŸããã 仿¥ããããã¯
åé€ãããŸãã ïŒåé€ãããã®ã§ããããŸã§åæ¢ãããã ãã§ãïŒã ãããã圌ãã¯ããã£ã³ãã«ãäœæãããšãã«
ãã©ã³ã¹ãã©ã³ã¹ãã¥ãŒãµãŒãæå®ããããšãèš±å¯ããŸããïŒ
;; project.clj (require '[clojure.core.async :as a]) ;; (def xf (filter odd?)) ;; (def ch (a/chan 10 xf)) ;; 0 9 (a/onto-chan ch (range 10)) ;; (a/<!! (a/into [] ch)) ;; => [1 3 5 7 9]
ãã©ã³ã¹ãã¥ãŒãµãŒã¯ãç·©è¡ããããã£ã³ãã«ã«ã®ã¿æããããšãã§ããŸãã ãããŠãèŠçŽ ããããã¡ã«è¡šç€ºãããåã«ããã©ã³ã¹ãã¥ãŒãµã¯ãããåŠçããŸãã ããããçš®é¡ã®
ãã€ãã©ã€ã³ãããããã©ã³ã¹ãã¥ãŒãµãŒã§ãåäœããŸãã
ãŸãšãããš
ããŸããŸãªã¬ãžã¥ãŒãµãŒ/ãã©ã³ã¹ãã¥ãŒãµãŒã¯ãã¹ãŠãç³ã¿èŸŒã¿æŒç®ã®äžè¬åã§ãã ãããã£ãŠããããã䜿çšããã«ã¯ã2ã€ã®åŒæ°ãæã€éå
颿°ãå¿
èŠã§ãã
2é²ãªãã·ã§ã³ã«å ããŠã0é²ãªãã·ã§ã³ã決å®ããããšããå§ãããŸããç³ã¿èŸŒã¿ã®åæç¶æ
ãæå®ãããŠããªãå Žåã«äœ¿çšã§ããŸãã ãŸãã¯ã䜿çšãããªãå ŽåããããŸããå
ã®ã³ã¬ã¯ã·ã§ã³ã空ã§ãªãå Žåã
reduce
ã¯æåã®èŠçŽ ãåããŸãã ãããã
transduce
ã¯ããã»ã©æå³ã®ããåäœãããŸãã-åæç¶æ
ãæç€ºçã«æž¡ãããããreduct颿°ã®0é
åŒã³åºãã䜿çšãããŸãã
äžæ¹ã
transduce
ã¯éå
颿°ããããå€ããå¿
èŠãšããŸã-1é
ãªãã·ã§ã³ãå¿
èŠã§ãã ããã¯ãäžè¬çãªå Žåãã»ãšãã©äœãããŸããã çå£ã«ãéåžžããã®å Žåã¯
([x] x)
ãæãæå³ã®ããå®è£
ã§ãã ããããç§ãã¡ã¯æ ãè
ã§ãå€ã颿°ïŒ0/2é
ïŒãæžãæããã®ãé¢åãªã®ã§ã空ã®1é
ãªãã·ã§ã³ã远å ãã
completing
ã©ãããŒã䜿çšããŸãã
ããã«ãæžéæ©ã¯å€å§åšã«åºã¥ããŠããŸãã Transformer =
rf -> rf
ã¿ã€ãã®é¢æ°ã å®éãæžéæ©ã¯ãå€å§åšããã£ãããšãã蟌ãŸããã³ã¬ã¯ã·ã§ã³ã§ãã ãããŠããã®ã³ã¬ã¯ã·ã§ã³ã§
reduce
ãå®è¡
reduce
ãã³ã«ãæåã«ãã©ã³ã¹ãã©ãŒããŒãreduct颿°ããå°ç¡ãã«ããŸããã
倿åšã=倿åšã1é
éå
颿°ã®ãµããŒãã®ã¿ãå¿
èŠã§ãã ãããã£ãŠããã®æãäžå¹žãª1-arnikãåžžã«å®çŸ©ããèªãããã«å®£èšããŸããããã¡ãããå€ããã©ã³ã¹ã¯äœ¿çšããããã©ã³ã¹ãã¥ãŒãµãŒã®ã¿ã䜿çšããŸããã
ãã®ãã¹ãŠã«ããããã©ã³ã¹ãã¥ãŒãµãŒã¯ã³ã¬ã¯ã·ã§ã³ã®æäœã«éå®ãããŸããã ãããããã£ãã«ãå
¥åºåã¹ããªãŒã ããã¥ãŒããªãã¶ãŒããŒãªã©ã«åºå®ã§ããŸãã äžè¬ã«ããã®ãã¹ãŠã®ãã¡ã³ã¿ãžãŒã«ã¯ååã§ãã
åèšïŒ
- , ;
- , I/O, â
reducers
; reduce
â transduce
;- â ;
- , ⊠;
- â
map
, filter
.