Clojure for PHP Developers

Clojure for PHP Developers

My introduction to Clojure from PHP Tek 12 #tek12

47d1af0e885746e39195c8ff3234f47d?s=128

Ian Barber

May 25, 2012
Tweet

Transcript

  1. 3.

    INSTALLING CLOJURE mac osx $ brew install rlwrap leiningen debian

    / ubtuntu $ apt-get install leiningen windows https://github.com/technomancy/leiningen http://dev.clojure.org/display/doc/Getting+Started
  2. 6.

    (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 speed https://github.com/ianbarber/Boids
  3. 7.

    /* 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) ); }
  4. 8.

    /* 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) ); }
  5. 9.

    /* 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 += (:x boid) sum_y += (:y boid) } x_average = (/ sum_x boid_count) y_average = (/ sum_y boid_count) [ (- x_average x) (- y_average y) ] )
  6. 10.

    (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) ] )
  7. 11.

    (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));
  8. 12.

    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"))
  9. 13.

    SEQUENCES Refs Atomics Agents (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)
  10. 14.

    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"
  11. 15.

    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"
  12. 17.
  13. 18.

    Refs Atomics Agents (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}
  14. 19.

    STM - REFS Refs Atomics Agents (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
  15. 20.

    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)} )
  16. 21.

    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"
  17. 22.

    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
  18. 23.

    (defpage [:post "/verbatim"] {text :text :or {text ""}} (if (blank?

    text) (resp/json {:error "Invalid Input"}) (resp/json {:tagged (tagger (tokeniser text))} )))
  19. 24.

    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"],["?","."]]}
  20. 25.

    (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)))))