# mainstreamless## Clojure 00
Никита Прокоповtonsky.livejournal.com
6 марта 2013
# Причины создания
clojure.org/rationale
Развитая платформаЛИСПФункциональное программированиеConcurrency
# JVM
БыстраяКачественнаяУровенем выше ОС, лучше абстракцииВалом библиотекВалом инструментов
# JVM
Уважает платформуПисать джаву на кложе проще, чем на джавеclj strings == java stringsclj numbers == java numbersclj nil == java null
# LISP
ГибкийДинамичный — новое для JVMМаленькое ядро → портируемостьПочти нет синтаксисаКод-как-данные
# LISP
def if do let quote var fnloop recurthrow trymonitor-entermonitor-exit. new set!
# LISP
REPLОткрытость — всё управляемоДаже синтаксис!
# ФП
Удобный инструментFirst-class functionsLexical closuresЛенивостьDynamic typing
# Как это выглядит
public class StringUtils { public static boolean isBlank(String str) { int strLen; if (str == null || (strLen = str.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if ((Character.isWhitespace(str.charAt(i)) == false)) { return false; } } return true; }}
# Как это выглядит
(defn blank? [s] (every? #(Character/isWhitespace %) s))
# Как это выглядит
public class StringUtils { public static boolean isBlank(String str) { int strLen; if (str == null || (strLen = str.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if ((Character.isWhitespace(str.charAt(i)) == false)) { return false; } } return true; }}
(defn blank? [s] (every? #(Character/isWhitespace %) s))
# Синтаксис
method()
method(arg)
object.method(arg)
Map<String, String> map =new HashMap<String, String>();map.put(“key”, “value”);
(f)
(f arg)
(f object arg), (.method o a)
(def map {:key “value”})
# Синтаксис
(defn f [x y] (+ x y))
[1 2 3](1 2 3){:x 1 :y 2}#{:x :y :z}
# Философия
См. youtube.com/clojuretv
Особенно (!) Rich Hickey
# Открывайте данные
Программы перемалывают данныеНе прячьте их
“It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures.”
# Открывайте данные
distinct filter remove for keep keep-indexed consconcat lazy-cat mapcat cycle interleave interposerest next fnext nnext drop drop-while nthnext fortake take-nth take-while butlast drop-last for flat-ten reverse sort sort-by shuffle split-at split-withpartition partition-all partition-by map pmap mapcatfor replace reductions map-indexed seque first ffirstnfirst second nth when-first last rand-nth zipmapinto reduce set vec into-array to-array-2d frequen-cies group-by apply not-empty some reduce seq? eve-ry? not-every? not-any? empty? some filter doseq do-run doall realized? seq vals keys rseq subseq rsubseqlazy-seq repeatedly iterate repeat range line-seqresultset-seq re-seq tree-seq file-seq xml-seq itera-
# Decomplecting
Var = value + timeObject = state + identity + valueMethod = func + state + namespaceActors = what + whoLoops = what + how...
# Открытость
Мультиметоды, протоколыМетаданныеPredicate dispatch вместо pattern matchingComposable abstractions
$().click().css() или (-> ($ ...) (click ) (css))
# Переиспользуемость
Неймспейсится всёНет custom reader, есть EDNПолиморфизм через протоколы
# Комбинируемость
Avoid things that do not compose
Manual lockingImperative code
# Concurrency## Задача
колония муравьев собирает пищукаждый муравей — отдельный потокобщая карта едырисовать положение дел
# Concurrency## Задача
# Concurrency## Проблемы
неатомарные операциисогласованное принятие решенийкогерентное состояние мира
# Проблемы многопоточного программирования
«Мир» постоянно меняетсяПросадка скорости на syncsDead locksLive locksЛегко ошибитьсяСложно просчитать вариантыСложно тестировать
# Immutable data structures
Легко шарить между потокамиОперации атомарны по определениюЕдят кучу памяти (медленно?)
# Persistent data structures
«Умно» делят общие частиЕдят мало памятиБыстрые (почти константная стоимость)Портированы в Scala :)
# List
1 2 3
list1headtail
list2headtail
list3headtail
# Vector
v
# Vector
v
# Vector
v
# Vector
v
# Vector
v
# Vector
v
# Vector
v
......
# Vector
v
......
up to 32 elms
log32 (s
ize)
# Vector
v
......
up to 32 elms
log32 (s
ize)
00[00000][00000][00000][00000][00001][00100]
# Map## Hash trie
# Map
# Atoms
(def x (atom 1));; #’user/x
(swap! x inc);; 2
(swap! x inc);; 3
(swap! x inc) ;; 10 (?)
(swap! x #(Math/sin %));; -0.544...
# Atoms
1
x
# Atoms
1 2
x
(f 1)
# Atoms
1 2
x
swap!
# Atoms
1 2
x
# Atoms
1 2 3
x
(f 2)
# Atoms
1 2 3
x
swap!
# Atoms
1 2 3
x
# Atoms
1 2 3
x@x
# Atoms
1 2 3
x
(f (f 1))
@x
# Atoms
Для «простого» mutable stateЯвно выделенная «мутация»Атомарное изменениеЛюбое значение — это всегда результат последовательного применения функций
# Atoms## Конфликты
1 2 3
x
(f 2)
−2
1 2 3
x
(f −2)−2 −1
# Atoms## Конфликты
1 2 3
x
swap!−2 −1
# Atoms## Конфликты
# Agents
(def x (agent 1));; #’user/x
(send x inc);; #<Agent@73703457: 2>
(send x inc);; #<Agent@73703457: 3>
(send x (fn [a] (Thread/sleep 1000) (inc a)));; #<Agent@73703457: 3>
@x;; #<Agent@73703457: 3>
@x;; #<Agent@73703457: 4>
# Agent
2
gf
h
thread pool
# Agent
2
hgf
thread pool
# Agent
2
hg
thread pool
f
# Agent
2
hg
thread pool
f
(f 2)
# Agent
3
hg
thread pool
(f 2)
# Agent
3
hg
thread pool
# Agent
3
h
thread pool
g
# Agent
Unit of workПохож на atoms, только…Для последовательных операций:heavy lifting, сохранение в файл, запись в сеть,
конечные автоматы, … Выполняется в отдельном потокеОчередь сообщенийВсегда наблюдаемое состояние
# STM
Согласованное изменение состоянияПроще рассуждатьСложнее ошибитьсяComposableАгенты работают с STM!
# STM
# Concurrency
ИммутабельностьПерсистентные структуры данныхSoftware transactional memoryLock-free
ComposableБезопасно!
# mainstreamless## Clojure 00
Никита Прокоповtonsky.livejournal.com
6 марта 2013