Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Clojure: Return of the Jedi

Clojure: Return of the Jedi

My Clojure presentation from OpenFest 2012

Bozhidar Batsov

November 03, 2012
Tweet

More Decks by Bozhidar Batsov

Other Decks in Programming

Transcript

  1. bozhidar user> (:twitter bozhidar) "@bbatsov" user> (bozhidar :blog) "http://batsov.com" user>

    (:github bozhidar) "http://github.com/bbatsov" Saturday, November 3, 12
  2. Затънали сме до уши в калта наречена “инцидентна сложност” и

    въобще не си даваме сметка за това... Saturday, November 3, 12
  3. public boolean hasUpperCase(String word) { if (word == null) {

    return false; } int len = word.length(); for (int i = 0; i < len; i++) { if (Character.isUpperCase(word.charAt(i))) { return true; } } return false; } (defn has-uppercase? [string] (some #(Character/isUpperCase %) string)) Saturday, November 3, 12
  4. Магията на Lisp • Половин вековна история • Често имитиран,

    вечно ненадминат • Изключително малко ядро • Почти никакъв синтаксис • “Кодът е данни” (code is data) • Интерактивно програмиране Saturday, November 3, 12
  5. Проблемите на Lisp (Common Lisp/Scheme) • Никаква иновация след стандартизирането

    им • Сегментация • Думата “едновременно” (concurrently) не се споменава в спецификациите им • Повечето Lisp-ове дефинират сами своята платформа Saturday, November 3, 12
  6. "We were after the C++ programmers. We managed to drag

    a lot of them about halfway to Lisp." Saturday, November 3, 12
  7. Ruby was a Lisp originally, in theory. “Ruby was a

    Lisp originally, in theory.” Saturday, November 3, 12
  8. Голяма част от езиците, които стават за нещо са повлияни

    пряко или косвено от Lisp!!! Saturday, November 3, 12
  9. A language that doesn’t affect the way you think about

    programming is not worth knowing. Saturday, November 3, 12
  10. Есенцията • Динамичен език за програмиране • JVM/CLR/JavaScript • Модерен

    диалеакт на Lisp (1) • Функционален по практичен начин • Оптимизиран за паралелно програмиране • Борец за един по-прост свят Saturday, November 3, 12
  11. Еволюцията на Lisp • сбогом car & cdr (hello first

    & rest) • по-малко скоби • повече структури от данни с literal синтаксис (set, map, vector) • коварно бърз runtime • стандартизиран runtime • непроменими (immutable) структури данни Saturday, November 3, 12
  12. (hello clojure) (defn hello-world [] (println "Hello, world!")) (defn hello

    [name] (println (format "Hello, %s!" name))) Saturday, November 3, 12
  13. Структури от данни • свързан списък (list) • множество (set)

    • вектор • асоциативен масив (map/dictionary) • всичко Джавешко и родно Saturday, November 3, 12
  14. user> (list 1 2 3) (1 2 3) user> '(1

    2 3) (1 2 3) user> (def names '("Bozhidar" "Snezhi" "Batman" "Yoda" "Mike")) #'user/names user> (first names) "Bozhidar" user> (rest names) ("Snezhi" "Batman" "Yoda" "Mike") user> (last names) "Mike" user> (count names) 5 user> (map lower-case names) ("bozhidar" "snezhi" "batman" "yoda" "mike") user> (map count names) (8 6 6 4 4) user> (apply + (map count names)) 28 user> (cons "Pesho" names) ("Pesho" "Bozhidar" "Snezhi" "Batman" "Yoda" "Mike") user> names ("Bozhidar" "Snezhi" "Batman" "Yoda" "Mike") user> (conj names "Pesho") ("Pesho" "Bozhidar" "Snezhi" "Batman" "Yoda" "Mike") Saturday, November 3, 12
  15. user> (filter even? (range 1 10)) (2 4 6 8)

    user> (every? even? (range 1 10)) false user> (every? even? (filter even? (range 1 10))) true user> (map #(+ % 5) (range 1 10)) (6 7 8 9 10 11 12 13 14) user> (map (partial + 5) (range 1 10)) (6 7 8 9 10 11 12 13 14) user> (map (comp (partial * 2) (partial + 5)) (range 1 10)) (12 14 16 18 20 22 24 26 28) Saturday, November 3, 12
  16. user> (doc and) ------------------------- clojure.core/and ([] [x] [x & next])

    Macro Evaluates exprs one at a time, from left to right. If a form returns logical false (nil or false), and returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expr. (and) returns true. nil user> (source and) (defmacro and "Evaluates exprs one at a time, from left to right. If a form returns logical false (nil or false), and returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expr. (and) returns true." {:added "1.0"} ([] true) ([x] x) ([x & next] `(let [and# ~x] (if and# (and ~@next) and#)))) nil Saturday, November 3, 12
  17. user> (set '(1 1 2 2 3 3)) #{1 2

    3} user> (def a-set #{1 2 3 4 5}) #'user/a-set user> (contains? a-set 3) true user> (contains? a-set 9) false user> (conj a-set 5) #{1 2 3 4 5} user> (conj a-set 6) #{1 2 3 4 5 6} user> (use 'clojure.set) nil user> (intersection #{1 2 3} #{2 3 4}) #{2 3} user> (difference #{1 2 3} #{2 3 4}) #{1} user> (union #{1 2 3} #{2 3 4}) #{1 2 3 4} Saturday, November 3, 12
  18. user> (hash-map 1 2 3 4) {1 2, 3 4}

    user> (hash-map "Batman" "Bruce Wayne" "Superman" "Clark Kent") {"Batman" "Bruce Wayne", "Superman" "Clark Kent"} user> {:batman "Bruce Wayne", :superman "Clark Kent"} {:superman "Clark Kent", :batman "Bruce Wayne"} user> (def a-map {:batman "Bruce Wayne", :superman "Clark Kent"}) #'user/a-map user> (:superman a-map) "Clark Kent" user> (a-map :batman) "Bruce Wayne" user> (a-map :zorro) nil user> (merge a-map {:zorro "Diego de la Vega"}) {:superman "Clark Kent", :batman "Bruce Wayne", :zorro "Diego de la Vega"} user> a-map {:superman "Clark Kent", :batman "Bruce Wayne"} user> (contains? a-map :batman) true user> (assoc a-map :catwoman "Selina Kyle") {:superman "Clark Kent", :batman "Bruce Wayne", :catwoman "Selina Kyle"} user> a-map {:superman "Clark Kent", :batman "Bruce Wayne"} user> (dissoc a-map :batman) {:superman "Clark Kent"} user> a-map {:superman "Clark Kent", :batman "Bruce Wayne"} Saturday, November 3, 12
  19. user> (vector 1 2 3 4) [1 2 3 4]

    user> (into [] '(1 2 3 4)) [1 2 3 4] user> (def v (into [] (range 1 5))) #'user/v user> (count v) 4 user> (nth v 0) 1 user> (conj v 5) [1 2 3 4 5] user> (pop v) [1 2 3] user> (peek v) 4 user> [1 2 3 4] [1 2 3 4] Saturday, November 3, 12
  20. user> (def f (future (Thread/sleep 10000) (println "done") 100)) #'user/f

    user> f #<core$future_call$reify__5684@201075c5: :pending> user> @f done 100 user> @f 100 user> (def my-delay (delay (println "did some work") 100)) #'user/my-delay user> @my-delay did some work 100 user> @my-delay 100 Saturday, November 3, 12
  21. user> (defn slow-op [n] (Thread/sleep 5000) n) #'user/slow-op user> (map

    slow-op (range 1 5)) (1 2 3 4) user> (time (doall (map slow-op (range 1 5)))) "Elapsed time: 20004.081 msecs" (1 2 3 4) user> (time (doall (pmap slow-op (range 1 5)))) "Elapsed time: 5002.705 msecs" (1 2 3 4) Saturday, November 3, 12
  22. (def picked-numbers (ref #{})) (def secret-num (.nextInt (java.util.Random.) 10)) (defn

    guess-number [n] (print "Enter a guess between 1 and 10: ") (flush) (let [guess (java.lang.Integer/parseInt (read-line)) ] (cond (= guess n) (println "You guessed correctly") (contains? (deref picked-numbers) n) (println "Pick another number!") :else (dosync (alter picked-numbers conj guess))))) Saturday, November 3, 12
  23. user> (guess-number secret-num) Enter a guess between 1 and 10:

    1 #{1} user> (guess-number secret-num) Enter a guess between 1 and 10: 2 #{1 2} user> (guess-number secret-num) Enter a guess between 1 and 10: 3 #{1 2 3} ... user> (guess-number secret-num) Enter a guess between 1 and 10: 7 #{1 2 3 4 5 6 7} user> (guess-number secret-num) Enter a guess between 1 and 10: 8 #{1 2 3 4 5 6 7 8} user> (guess-number secret-num) Enter a guess between 1 and 10: 9 You guessed correctly Saturday, November 3, 12
  24. (def picked-numbers (atom #{})) (def secret-num (.nextInt (java.util.Random.) 10)) (defn

    guess-number [n] (print "Enter a guess between 1 and 10: ") (flush) (let [guess (java.lang.Integer/parseInt (read-line)) ] (cond (= guess n) (println "You guessed correctly") (contains? (deref picked-numbers) n) (println "Pick another number!") :else (swap! picked-numbers conj guess)))) Saturday, November 3, 12
  25. user> (def some-agent (agent 0)) #'user/some-agent user> (dotimes [i 100]

    (send some-agent inc)) nil user> some-agent #<Agent@1997c457: 100> user> @some-agent 100 Saturday, November 3, 12
  26. Звучи добре, ама дали ще я бъде тая работа? •

    Добри програмисти се изнасят на талази към Clojure • O’Reilly издадоха книга за Clojure!!! • Thoughtbot съветва компаниите да залагат на Clojure Saturday, November 3, 12
  27. Инструменти за масово разрушение • Leiningen 2 • Emacs •

    clojure-mode • paredit • nrepl.el Saturday, November 3, 12