План
- демо: как начать
- демо: синтаксис и Emacs
- демо: Clony
- повседневное
- core.matrix
- CodeNotes
- vs Erlang
Демо
Как начать: Leiningen
Демо
синтаксис, Emacs, nrepl, paredit
WARNING
Слайды далее полны необоснованных утверждений
Seq
- универсальная абстракция
- Seqable
- линейная
- ленивая (!)
- chunked
- много функций для работы с Seq
(for [x [1 2 3]]
(prn x))
(doseq [x [1 2 3]]
(prn x))
Структуры данных: vector
- ordered
- иммутабельный
- гетерогенный
- O(log32) get/set/delete
- O(1) append (справа)
- Seqable
(def test-vec [1 :a 2 3])
(test-vec 1) ; :a
(take 2 test-vec) ; (1 :a)
Структуры данных: map
- O(log32) get/set/delete/insert
- Seqable
(def test-map {:a 1 :b 2})
(test-map :a) ; 1
(:a test-map) ; 1
(get test-map :a) ; 1
(seq test-map) ; ([:a 1] [:b 2]) — KVPairs!
(for [[k v] test-map] …)
Atoms
- CAS семантика
- swap!/reset!
- watchers
- кеши, system state в map'е
(def test-atom (atom 0))
@test-atom ; 0
(swap! test-atom + 2) ; 3
@test-atom ; 3
(reset! test-atom 42) ; 42
@test-atom ; 42
Arrow macros
(-> 1 (+ ,,, 2) (* ,,, 3))
Arrow macros
(def test-map {:a {:b 2}))
(-> test-map (:a) (:b)) ; 2
Arrow macros
(def test-map {:a {:b 2}))
(-> test-map :a :b) ; 2
Arrow macros
(def some-vector […])
(->> some-vector (take 2) (map some-fn) vec)
Arrow macros
(-> headers
(safe-get :x-ratelimit-reset)
Long/parseLong
(* 1000)
timec/from-long
timec/to-string)
- GSoC 2013
- матричная библиотека на чистом Clojure
- сравнимая с Java скорость
- low-level
JVM!
- slow Clojure: reflection
- fast Clojure: type hints
(deftype NDArray
[^doubles data
^int ndims
^ints shape
^ints strides
^int offset])
±10% Java
JVM!
- slow Clojure: Object
- fast Clojure: primitive
(defn dot-product [^doubles ws ^doubles xs]
(areduce xs i ret 0.0
(+ ret (* (aget xs i)
(aget ws i)))))
±10% Java
macros!
(c-for [k (int 0) (< k n) (inc k)]
(aset a (inc (aget a k))))
macros!
(require '[hiphip.double :as dbl])
(defn dot-product [ws xs]
(dbl/asum [x xs w ws] (* x w)))
Уроки core.matrix
- очень легко написать эффективный tight loop
- генерация кода для примитивов (полиморфизм для бедных)
- макросы очень полезны!
- баг (?) в Clojure замедляет компиляцию больших (10KLOC+) сорцев с тайпхинтами
- AOT помогает
- победитель ClojureCup 2013
- отсутствующий таск-трекер
- очень легко писать код
- очень легко наговнякать рабочее решение
- рефакторить несложно
- но нужно рефакторить
Идеология
- libraries >>> frameworks
- Fine-grained, Composable Abstractions (FCA)
- очень много готовых либ
- много очень крутых либ
- постоянные парадоксы выбора (большой search space)
- как организовать приложение?
Anecdotal evidence
- 1-4 человека (мы): совместное владение кодом + рефакторинг
- …
- 10+ людей (Prismatic): свои абстракции (не фреймворки!)
- гораздо шире возможности
- очень много сахара
- инфраструктура и экосистема гораздо лучше, чем у Erlang
core.async (vs Erlang)
- first-order channels
- больше свободы, чем с акторами
- чуть сложнее, чем с акторами
- лучше, чем акторы?
Актор
(go (loop []
(when-let [msg (<! cs-c)]
(handler system config user msg sc-c)
(recur))))
- core.async + core.match позволяют эмулировать акторов
- …но нет желания
- эмуляция дерева супервизоров неудобна
- …сложность обработки ошибок в JVM?
- можно выразить очень сложную логику коротко (conditional retry в 10 строк)
Erlang:
- узкие ниши (стриминговый сервер, «умный» роутер) ИЛИ
- большие команды
Clojure:
- маленькие высокопрофессиональные команды И
- сложные задачи
- очень приятный язык
- невероятно гибкий
- никакого BDSM
- очень помогает в programming in the small
- (пока) хуже помогает в programming in the large
Учите Clojure!
Programming Clojure, Joy of Clojure