Created
January 22, 2014 22:31
-
-
Save cgrand/8568717 to your computer and use it in GitHub Desktop.
Mon historique de l'atelier data vs fns du Paris Clojure User Group http://www.meetup.com/Paris-Clojure-User-Group/ du 22 Janvier 2014
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
;; Clojure 1.5.1 | |
=> ; coll (fn [f acc]) renvoie (reduce f acc coll) | |
=> ; coll (fn [f init]) renvoie (reduce f init coll) | |
=> (defn fnil [f init] init) | |
WARNING: fnil already refers to: #'clojure.core/fnil in namespace: cljug.core, being replaced by: #'cljug.core/fnil | |
#'cljug.core/fnil | |
=> (reduce + 0 nil) | |
0 | |
=> (fnil + 0) | |
0 | |
=> (defn fcons [x fcoll] | |
(fn [f init] | |
#_(reduce f init (cons x coll)) | |
#_(reduce f (f init x) coll) | |
(fcoll f (f init x)))) | |
#'cljug.core/fcons | |
=> (fcons 1 (fcons 2 (fcons 3 fnil))) | |
#<core$fcons$fn__1571 cljug.core$fcons$fn__1571@ad5da47> | |
=> (*1 + 0) | |
6 | |
=> (*2 conj []) | |
[1 2 3] | |
=> (defn fcons [head ftail] | |
(fn [f init] | |
(ftail f (f init head)))) | |
#'cljug.core/fcons | |
=> (defn fmap [g fcoll] | |
(fn [f init] | |
#_(reduce f init (map g coll)) | |
#_(reduce (fn [acc x] (f acc x)) init (map g coll)) | |
#_(reduce (fn [acc x] (f acc (g x))) init coll) | |
(fcoll (fn [acc x] (f acc (g x))) init))) | |
#'cljug.core/fmap | |
=> (fmap inc (fcons 1 (fcons 2 (fcons 3 fnil)))) | |
#<core$fmap$fn__1844 cljug.core$fmap$fn__1844@2795804b> | |
=> (*1 conj []) | |
[2 3 4] | |
=> (defn ffilter [pred fcoll] | |
(fn [f init] | |
#_(reduce f init (filter pred coll)) | |
#_(reduce (fn [acc x] (f acc x)) init (filter pred coll)) | |
#_(reduce (fn [acc x] | |
(if (pred x) | |
(f acc x) | |
acc)) init coll) | |
(fcoll (fn [acc x] | |
(if (pred x) | |
(f acc x) | |
acc)) init))) | |
#'cljug.core/ffilter | |
=> (ffilter odd? (fcons 1 (fcons 2 (fcons 3 fnil)))) | |
#<core$ffilter$fn__2101 cljug.core$ffilter$fn__2101@3f047fc3> | |
=> (*1 conj []) | |
[1 3] | |
=> (fmap inc (ffilter odd? (fcons 1 (fcons 2 (fcons 3 fnil))))) | |
#<core$fmap$fn__1844 cljug.core$fmap$fn__1844@5c7b1ff8> | |
=> (*1 conj []) | |
[2 4] | |
=> (defn reducer [xf] | |
(fn [f init] | |
(fcoll (xf f) init))) | |
CompilerException java.lang.RuntimeException: Unable to resolve symbol: fcoll in this context, compiling:(NO_SOURCE_PATH:3:5) | |
=> (defn reducer [xf fcoll] | |
(fn [f init] | |
(fcoll (xf f) init))) | |
#'cljug.core/reducer | |
=> (defn ffilter2 [pred fcoll] | |
(reducer (fn [f] | |
(fn [acc x] | |
(if (pred x) | |
(f acc x) | |
acc))))) | |
#'cljug.core/ffilter2 | |
=> (fmap inc (ffilter2 odd? (fcons 1 (fcons 2 (fcons 3 fnil))))) | |
ArityException Wrong number of args (1) passed to: core$reducer clojure.lang.AFn.throwArity (AFn.java:437) | |
=> (defn ffilter2 [pred fcoll] | |
(reducer (fn [f] | |
(fn [acc x] | |
(if (pred x) | |
(f acc x) | |
acc))) | |
fcoll)) | |
#'cljug.core/ffilter2 | |
=> (fmap inc (ffilter2 odd? (fcons 1 (fcons 2 (fcons 3 fnil))))) | |
#<core$fmap$fn__1844 cljug.core$fmap$fn__1844@14268c02> | |
=> (*1 conj []) | |
[2 4] | |
=> (defn fmap2 [g fcoll] | |
(reducer (fn [f] | |
(fn [acc x] | |
(f acc (g x)))) | |
fcoll)) | |
#'cljug.core/fmap2 | |
=> ;; similaire code des vrais reducers | |
=> ;; FIN ETAPE 1 | |
=> (use 'clojure.repl) | |
nil | |
=> (doc every-pred) | |
------------------------- | |
clojure.core/every-pred | |
([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps]) | |
Takes a set of predicates and returns a function f that returns true if all of its | |
composing predicates return a logical true value against all of its arguments, else it returns | |
false. Note that f is short-circuiting in that it will stop execution on the first | |
argument that triggers a logical false result against the original predicates. | |
nil | |
=> ((every-pred odd? even?) 0) | |
false | |
=> ((every-pred odd? even?) 1) | |
false | |
=> ((every-pred odd? #(> % 5)) 1) | |
false | |
=> ((every-pred odd? #(> % 5)) 20) | |
false | |
=> ((every-pred odd? #(> % 5)) 21) | |
true | |
=> (defn every-pred [& preds] | |
(fn [x] | |
(reduce (fn [acc pred] | |
(and acc (pred x))) | |
true preds))) | |
WARNING: every-pred already refers to: #'clojure.core/every-pred in namespace: cljug.core, being replaced by: #'cljug.core/every-pred | |
#'cljug.core/every-pred | |
=> ((every-pred odd? #(> % 5)) 21) | |
true | |
=> ((every-pred odd? #(> % 5)) 20) | |
false | |
=> ((every-pred odd? #(> % 5)) 1) | |
false | |
=> (defn every-pred [& preds] | |
(fn [x] | |
(reduce (fn [acc pred] | |
(if (pred x) | |
acc ; always true | |
(reduced false))) | |
true preds))) | |
#'cljug.core/every-pred | |
=> (defn every-pred [& preds] | |
(fn [x] | |
(every? (fn [pred] (pred x)) preds))) | |
#'cljug.core/every-pred | |
=> ((every-pred odd? #(> % 5)) 1) | |
false | |
=> (map (every-pred odd? #(> % 5)) [1 20 21 5]) | |
(false false true false) | |
=> (source clojure.core/every-pred) | |
(defn every-pred | |
"Takes a set of predicates and returns a function f that returns true if all of its | |
composing predicates return a logical true value against all of its arguments, else it returns | |
false. Note that f is short-circuiting in that it will stop execution on the first | |
argument that triggers a logical false result against the original predicates." | |
{:added "1.3"} | |
([p] | |
(fn ep1 | |
([] true) | |
([x] (boolean (p x))) | |
([x y] (boolean (and (p x) (p y)))) | |
([x y z] (boolean (and (p x) (p y) (p z)))) | |
([x y z & args] (boolean (and (ep1 x y z) | |
(every? p args)))))) | |
([p1 p2] | |
(fn ep2 | |
([] true) | |
([x] (boolean (and (p1 x) (p2 x)))) | |
([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y)))) | |
([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z)))) | |
([x y z & args] (boolean (and (ep2 x y z) | |
(every? #(and (p1 %) (p2 %)) args)))))) | |
([p1 p2 p3] | |
(fn ep3 | |
([] true) | |
([x] (boolean (and (p1 x) (p2 x) (p3 x)))) | |
([x y] (boolean (and (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y)))) | |
([x y z] (boolean (and (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y) (p1 z) (p2 z) (p3 z)))) | |
([x y z & args] (boolean (and (ep3 x y z) | |
(every? #(and (p1 %) (p2 %) (p3 %)) args)))))) | |
([p1 p2 p3 & ps] | |
(let [ps (list* p1 p2 p3 ps)] | |
(fn epn | |
([] true) | |
([x] (every? #(% x) ps)) | |
([x y] (every? #(and (% x) (% y)) ps)) | |
([x y z] (every? #(and (% x) (% y) (% z)) ps)) | |
([x y z & args] (boolean (and (epn x y z) | |
(every? #(every? % args) ps)))))))) | |
nil | |
=> (ns-unmap *ns* 'every-pred) | |
nil | |
=> every-pred | |
CompilerException java.lang.RuntimeException: Unable to resolve symbol: every-pred in this context, compiling:(NO_SOURCE_PATH:1:42) | |
=> (source clojure.core/every-pred) | |
(defn every-pred | |
"Takes a set of predicates and returns a function f that returns true if all of its | |
composing predicates return a logical true value against all of its arguments, else it returns | |
false. Note that f is short-circuiting in that it will stop execution on the first | |
argument that triggers a logical false result against the original predicates." | |
{:added "1.3"} | |
([p] | |
(fn ep1 | |
([] true) | |
([x] (boolean (p x))) | |
([x y] (boolean (and (p x) (p y)))) | |
([x y z] (boolean (and (p x) (p y) (p z)))) | |
([x y z & args] (boolean (and (ep1 x y z) | |
(every? p args)))))) | |
([p1 p2] | |
(fn ep2 | |
([] true) | |
([x] (boolean (and (p1 x) (p2 x)))) | |
([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y)))) | |
([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z)))) | |
([x y z & args] (boolean (and (ep2 x y z) | |
(every? #(and (p1 %) (p2 %)) args)))))) | |
([p1 p2 p3] | |
(fn ep3 | |
([] true) | |
([x] (boolean (and (p1 x) (p2 x) (p3 x)))) | |
([x y] (boolean (and (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y)))) | |
([x y z] (boolean (and (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y) (p1 z) (p2 z) (p3 z)))) | |
([x y z & args] (boolean (and (ep3 x y z) | |
(every? #(and (p1 %) (p2 %) (p3 %)) args)))))) | |
([p1 p2 p3 & ps] | |
(let [ps (list* p1 p2 p3 ps)] | |
(fn epn | |
([] true) | |
([x] (every? #(% x) ps)) | |
([x y] (every? #(and (% x) (% y)) ps)) | |
([x y z] (every? #(and (% x) (% y) (% z)) ps)) | |
([x y z & args] (boolean (and (epn x y z) | |
(every? #(every? % args) ps)))))))) | |
nil | |
=> (defn every-pred [& preds] | |
(fn [x] | |
(every? (fn [pred] (pred x)) preds))) | |
#'cljug.core/every-pred | |
=> (defn every-pred [& preds] | |
(reduce (fn [juxt-pred pred] | |
(fn [x] | |
(and (juxt-pred x) (pred x)))) | |
(constantly true) preds)) | |
#'cljug.core/every-pred | |
=> (map (every-pred odd? #(> % 5)) [1 20 21 5]) | |
(false false true false) | |
=> (defn every-pred [& preds] | |
(reduce (fn [juxt-pred pred] | |
(fn [x] | |
(and (juxt-pred x) (pred x)))) | |
(constantly true) preds)) | |
#'cljug.core/every-pred | |
=> ;; FIN ETAPE 2 | |
=> (defn comp [& fs] | |
(fn [x] | |
(reduce (fn [x f] (f x)) x (reverse fs)))) | |
WARNING: comp already refers to: #'clojure.core/comp in namespace: cljug.core, being replaced by: #'cljug.core/comp | |
#'cljug.core/comp | |
=> (defn comp [& fs] | |
(reduce (fn [comp-f f] | |
(fn [x] | |
(f (comp-f x)))) | |
identity (reverse fs))) | |
#'cljug.core/comp | |
=> ((comp inc #(* 2 %)) 1) | |
3 | |
=> (defn comp [& fs] | |
(reduce (fn [comp-f f] | |
(fn [x] | |
(comp-f (f x)))) | |
identity fs)) | |
#'cljug.core/comp | |
=> ((comp inc #(* 2 %)) 1) | |
3 | |
=> (partition-all (range 5)) | |
ArityException Wrong number of args (1) passed to: core$partition-all clojure.lang.AFn.throwArity (AFn.java:437) | |
=> (partition-all 2 (range 5)) | |
((0 1) (2 3) (4)) | |
=> (defn comp [& fs] | |
(letfn [(group [fs] | |
(let [fs (map (fn [[f g :as fs]] | |
(if (next fs) | |
(fn [x] (f (g x))) | |
f)) | |
(partition-all 2 fs))] | |
(if (next fs) | |
(recur fs) | |
(first fs))))] | |
(apply group fs))) | |
#'cljug.core/comp | |
=> ((comp inc #(* 2 %) dec) 1) | |
ArityException Wrong number of args (3) passed to: core$comp$group clojure.lang.AFn.throwArity (AFn.java:437) | |
=> (defn comp [& fs] | |
(letfn [(group [fs] | |
(let [fs (map (fn [[f g :as fs]] | |
(if (next fs) | |
(fn [x] (f (g x))) | |
f)) | |
(partition-all 2 fs))] | |
(if (next fs) | |
(recur fs) | |
(first fs))))] | |
(group fs))) | |
#'cljug.core/comp | |
=> ((comp inc #(* 2 %) dec) 1) | |
1 | |
=> ((comp inc #(* 2 %) dec) 10) | |
19 | |
=> (defrecord Comp [fs] | |
clojure.lang.IFn | |
(invoke [_ x] | |
(reduce (fn [x f] (f x)) x (rseq fs)))) | |
cljug.core.Comp | |
=> (defprotocol Composable | |
(compj [f g])) | |
Composable | |
=> (defrecord Comp [fs] | |
clojure.lang.IFn | |
(invoke [_ x] | |
(reduce (fn [x f] (f x)) x (rseq fs))) | |
Composable | |
(compj [f g] (Comp. (conj fs g)))) | |
cljug.core.Comp | |
=> (extend-protocol Composable | |
Object | |
(compj [f g] | |
(Comp. [f g]))) | |
nil | |
=> (compj (compj inc #(* 2 %)) dec) | |
#cljug.core.Comp{:fs [#<core$inc clojure.core$inc@59fdd712> #<core$eval4305$fn__4306 cljug.core$eval4305$fn__4306@2f93e4a8> #<core$dec clojure.core$dec@76ba6fe7>]} | |
=> (declare ->EvenComp ->OddComp) | |
#'cljug.core/->OddComp | |
=> (defrecord EvenComp [f] | |
clojure.lang.IFn | |
(invoke [_ x] | |
(f x)) | |
Composable | |
(compj [_ g] (->OddComp f g))) | |
cljug.core.EvenComp | |
=> (defrecord OddComp [f g] | |
clojure.lang.IFn | |
(invoke [_ x] | |
(f (g x))) | |
Composable | |
(compj [_ h] (->EvenComp (compj f #(g (h %)))))) | |
cljug.core.OddComp | |
=> (extend-protocol Composable | |
Object | |
(compj [f g] | |
(compj (->EvenComp f) g))) | |
nil | |
=> (compj (compj inc #(* 2 %)) dec) | |
#cljug.core.EvenComp{:f #cljug.core.OddComp{:f #<core$inc clojure.core$inc@59fdd712>, :g #<OddComp$fn__4506 cljug.core.OddComp$fn__4506@3815ac99>}} | |
=> (*1 10) | |
19 | |
=> (extend-protocol Composable | |
Object | |
(compj [f g] | |
(->OddComp f g))) | |
nil | |
=> (defrecord OddComp [f g] | |
clojure.lang.IFn | |
(invoke [_ x] | |
(f (g x))) | |
Composable | |
(compj [_ h] (compj f #(g (h %))))) | |
cljug.core.OddComp | |
=> ;; plus besoin de EvenComp | |
=> (compj (compj inc #(* 2 %)) dec) | |
#cljug.core.OddComp{:f #<core$inc clojure.core$inc@59fdd712>, :g #<OddComp$fn__4587 cljug.core.OddComp$fn__4587@2b4d2239>} | |
=> (*1 10) | |
19 | |
=> (compj (compj (compj inc #(* 2 %)) dec) identity) | |
#cljug.core.OddComp{:f #<core$inc clojure.core$inc@59fdd712>, :g #<OddComp$fn__4587 cljug.core.OddComp$fn__4587@6b61c3a0>} | |
=> (compj (compj (compj inc #(* 2 %)) dec) #(* 3)) | |
#cljug.core.OddComp{:f #<core$inc clojure.core$inc@59fdd712>, :g #<OddComp$fn__4587 cljug.core.OddComp$fn__4587@2aee41aa>} | |
=> (*1 10) | |
ArityException Wrong number of args (1) passed to: core$eval4638$fn clojure.lang.AFn.throwArity (AFn.java:437) | |
=> (compj (compj (compj inc #(* 2 %)) dec) #(* 3 %)) | |
#cljug.core.OddComp{:f #<core$inc clojure.core$inc@59fdd712>, :g #<OddComp$fn__4587 cljug.core.OddComp$fn__4587@56d3a88f>} | |
=> (*1 10) | |
59 | |
=> ;; et on peut appliquer la même technique (pair/impair, cf okasaki) pour réimplémenter fcons e manière arborescente | |
=> ;; exercice laissé à la charge du lecteur :-) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment