My introduction to Clojure from PHP Tek 12 #tek12
ian barber - [email protected] - @ianbarberCLOJUREFOR PHP DEVELOPERS
View Slide
WHAT ISCLOJURE ANDWHAT IS ITGOOD FOR?
INSTALLING CLOJUREmac osx$ brew install rlwrap leiningendebian / ubtuntu$ apt-get install leiningenwindowshttps://github.com/technomancy/leiningenhttp://dev.clojure.org/display/doc/Getting+Started
SEQUENCESCONCURRENCY WITH STMREPL$ lein replREPL started;user=>
READEVALUATEPRINTLOOP
(ns boids.core(:use [quil.core]))(def wwidth 646) ; Map width(def wheight 400) ; Map height(def avoid-dist 20) ; Stay this far apart(def col-dist 35) ; Avoid columns(def col-size 30) ; Column size(def infl-dist 100) ; Boids influence(def boid-count 50) ; How many boids(def boid-diam 5) ; Size of a boid(def max-speed 6) ; Boid max speedhttps://github.com/ianbarber/Boids
/* Head towards the rest of the boids */function attract($x, $y, $boids) {$cboids = closest($x, $y, $boids, 100);$boid_count = count($boids) == 0 ?count($boids) : 1;$sum_x = $sum_y = 0;foreach ($cboids as $boid) {$sum_x += $boid['x'];$sum_y += $boid['y'];}$x_average = $sum_x / $boid_count;$y_average = $sum_y / $boid_count;return array(($x_average - $x),($y_average - $y) );}
/* Head towards the rest of the boids */defn attract(x, y, boids) {cboids = closest(x, y, boids, 100);boid_count = count(boids) == 0 ?count(boids) : 1;sum_x = sum_y = 0;foreach (cboids as boid) {sum_x += boid['x'];sum_y += boid['y'];}x_average = sum_x / boid_count;y_average = sum_y / boid_count;return array((x_average - x),(y_average - y) );}
/* Head towards the rest of the boids */(defn attract [x y boids]cboids = (closest x y boids 100)boid_count = (count boids) == 0 ?(count boids) : 1sum_x = sum_y = 0foreach (cboids as boid) {sum_x += (:x boid)sum_y += (:y boid)}x_average = (/ sum_x boid_count)y_average = (/ sum_y boid_count)[ (- x_average x) (- y_average y) ])
(defn attract"Head towards the rest of the boids"[x y boids](let [cboids (closest x y boids 100)boid_count (if (= 0 (count boids))0 (count boids))[sum_x sum_y] foreach (cboids as boid){sum_x += (:x boid)sum_y += (:y boid)}x_average] (/ sum_x boid_count)y_average (/ sum_y boid_count)][ (- x_average x) (- y_average y) ])
(let [[sum_x sum_y] (reduce(fn [[sum_x sum_y] boid][(+ sum_x (:x boid))(+ sum_y (:y boid))][0 0]cboids)])list($sum_x, $sum_y) =array_reduce($cboids,function($boid, $sum) {return array($sum[0] + $boid['x'],$sum[1] + $boid['y']);}, array(0,0));
UNIT TESTING(ns boids.test.core(:use [boids.core] :reload)(:use [clojure.test]))(deftest test-create-boid(is (= 10 (:x (create-boid 10 0 0 0 [])))"Create boid does not include x val"))(deftest test-close-boids(is (= 1 (count (close-boids 60 60#{(create-boid 80 30 10 10 [])} 100 )))"Close boids does not include expected"))
SEQUENCESRefsAtomicsAgents(first '(1 2 3));; 1(nth [1 2 3] 1);; 2(first {:a 1 :b 2 :c 3});; [:a 1](rest #{:a :b :c});; (:c :b)(defn fib [a b](lazy-seq (cons a (fib b (+ b a)))));; #'user/fib(take 5 (fib 1 1));; (1 1 2 3 5)
INFINITE SEQUNCES(def users (cycle [1 2 3 4 5]))(defn slow-search [user](Thread/sleep 1000) (println "Loop")(if (> (rand-int 4) 1) true false))(def immediate-user(first (filter slow-search users)));; Loops 6 times(time (print immediate-user))(2)"Elapsed time: 0.119 msecs"
DELAYED EXECUTION(def lazy-user(take 1 (filter slow-search users)));; Immediate return(time (print lazy-user));; Loops 6 times(1) "Elapsed time: 5018.576 msecs"(time (print lazy-user))(1)"Elapsed time: 0.185 msecs"
CONCURRENCY WITH STM?CORECORE CORECORE
CONCURRENCY WITH STMA 1A 2A 3A 4STATEIDENTITY
RefsAtomicsAgents(defn updateit[] (swap! mystate assoc :punctuation "!"))(def mystate(atom {:name "hello" :value "world"}))(let [foo @mystate](future (updateit))(println foo) (println @mystate)(Thread/sleep 1000)(println foo) (println @mystate)){:name hello, :value world}{:name hello, :value world}{:name hello, :value world}{:punctuation !, :name hello, :value world}
STM - REFSRefsAtomicsAgents(def ted (ref 0)) (def bob (ref 0))(defn pickup [user gold](dosync (commute user + gold)))(defn transfer [from to gold](dosync(if (> (deref from) gold)(do (alter from - gold)(alter to + gold))false)))(pickup ted 100)(pickup bob 20)(transfer bob ted 25) ; false(transfer bob ted 19) ; 120 / 1
STM - AGENTS(def boids (take 5(repeatedly#(agent {:x (rand-int 100):y (rand-int 100)}))))(defn getav [dim b](int (/ (reduce + (map dim b)) (count b))))(defn behave [boid boids](Thread/sleep 5000){:x (getav :x boids) :y (getav :y boids)})
STM - AGENTS(doseq [boid boids](send boid behave(remove #(= @boid %) (map deref boids))))(time (apply await boids));; "Elapsed time: 9997.488 msecs"(doseq [boid boids](send-off boid behave(remove #(= @boid %) (map deref boids))))(time (apply await boids));; "Elapsed time: 4979.295 msecs"
LEIN PROJECT FILE(defproject textapp "0.1.0-SNAPSHOT":description"Simple text analysis rest service":dependencies [[org.clojure/clojure "1.3.0"][clojure-opennlp "0.1.9"][noir "1.2.1"]]:main textapp.server)https://github.com/ianbarber/Textservice$ lein noir new textapp
(defpage [:post "/verbatim"]{text :text :or {text ""}}(if (blank? text)(resp/json {:error "Invalid Input"})(resp/json{:tagged (tagger (tokeniser text))} )))
CALL FROM CURL$ curl -X POST http://localhost:8080/verbatim -d "text=Hello+world+how+are+things+with+you?"{"tagged":[["Hello","UH"],["world","NN"],["how","WRB"],["are","VBP"],["things","NNS"],["with","IN"],["you","PRP"],["?","."]]}
(defmethod make-pos-tagger POSModel[model](fn pos-tagger [tokens](let [token-array (into-array tokens)tagger (POSTaggerME. model *beam-size*)tags (.tag tagger token-array)](with-meta (map vector tokens tags)))))
http://clojure.org/WHERE TO GO NEXT?http://blip.tv/clojure
ian barber - [email protected] - @ianbarberTHANKS!
http://flickr.com/photos/usarmyafrica/4456204113http://flickr.com/photos/puliarfanita/6648892997IMAGE CREDITS