65
# mainstreamless ## Clojure 00 Никита Прокопов tonsky.livejournal.com 6 марта 2013

Введение в Clojure (Никита Прокопов)

Embed Size (px)

Citation preview

Page 1: Введение в Clojure (Никита Прокопов)

# mainstreamless## Clojure 00

Никита Прокоповtonsky.livejournal.com

6 марта 2013

Page 2: Введение в Clojure (Никита Прокопов)

# Причины создания

clojure.org/rationale

Развитая платформаЛИСПФункциональное программированиеConcurrency

Page 3: Введение в Clojure (Никита Прокопов)

# JVM

БыстраяКачественнаяУровенем выше ОС, лучше абстракцииВалом библиотекВалом инструментов

Page 4: Введение в Clojure (Никита Прокопов)

# JVM

Уважает платформуПисать джаву на кложе проще, чем на джавеclj strings == java stringsclj numbers == java numbersclj nil == java null

Page 5: Введение в Clojure (Никита Прокопов)

# LISP

ГибкийДинамичный — новое для JVMМаленькое ядро → портируемостьПочти нет синтаксисаКод-как-данные

Page 6: Введение в Clojure (Никита Прокопов)

# LISP

def if do let quote var fnloop recurthrow trymonitor-entermonitor-exit. new set!

Page 7: Введение в Clojure (Никита Прокопов)

# LISP

REPLОткрытость — всё управляемоДаже синтаксис!

Page 8: Введение в Clojure (Никита Прокопов)

# ФП

Удобный инструментFirst-class functionsLexical closuresЛенивостьDynamic typing

Page 9: Введение в Clojure (Никита Прокопов)

# Как это выглядит

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; }}

Page 10: Введение в Clojure (Никита Прокопов)

# Как это выглядит

(defn blank? [s] (every? #(Character/isWhitespace %) s))

Page 11: Введение в Clojure (Никита Прокопов)

# Как это выглядит

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

Page 12: Введение в Clojure (Никита Прокопов)

# Синтаксис

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”})

Page 13: Введение в Clojure (Никита Прокопов)

# Синтаксис

(defn f [x y] (+ x y))

[1 2 3](1 2 3){:x 1 :y 2}#{:x :y :z}

Page 14: Введение в Clojure (Никита Прокопов)

# Философия

См. youtube.com/clojuretv

Особенно (!) Rich Hickey

Page 15: Введение в Clojure (Никита Прокопов)

# Открывайте данные

Программы перемалывают данныеНе прячьте их

“It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures.”

Page 16: Введение в Clojure (Никита Прокопов)

# Открывайте данные

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-

Page 17: Введение в Clojure (Никита Прокопов)

# Decomplecting

Var = value + timeObject = state + identity + valueMethod = func + state + namespaceActors = what + whoLoops = what + how...

Page 18: Введение в Clojure (Никита Прокопов)

# Открытость

Мультиметоды, протоколыМетаданныеPredicate dispatch вместо pattern matchingComposable abstractions

$().click().css() или (-> ($ ...) (click ) (css))

Page 19: Введение в Clojure (Никита Прокопов)

# Переиспользуемость

Неймспейсится всёНет custom reader, есть EDNПолиморфизм через протоколы

Page 20: Введение в Clojure (Никита Прокопов)

# Комбинируемость

Avoid things that do not compose

Manual lockingImperative code

Page 21: Введение в Clojure (Никита Прокопов)

# Concurrency## Задача

колония муравьев собирает пищукаждый муравей — отдельный потокобщая карта едырисовать положение дел

Page 22: Введение в Clojure (Никита Прокопов)

# Concurrency## Задача

Page 23: Введение в Clojure (Никита Прокопов)

# Concurrency## Проблемы

неатомарные операциисогласованное принятие решенийкогерентное состояние мира

Page 24: Введение в Clojure (Никита Прокопов)

# Проблемы многопоточного программирования

«Мир» постоянно меняетсяПросадка скорости на syncsDead locksLive locksЛегко ошибитьсяСложно просчитать вариантыСложно тестировать

Page 25: Введение в Clojure (Никита Прокопов)

# Immutable data structures

Легко шарить между потокамиОперации атомарны по определениюЕдят кучу памяти (медленно?)

Page 26: Введение в Clojure (Никита Прокопов)

# Persistent data structures

«Умно» делят общие частиЕдят мало памятиБыстрые (почти константная стоимость)Портированы в Scala :)

Page 27: Введение в Clojure (Никита Прокопов)

# List

1 2 3

list1headtail

list2headtail

list3headtail

Page 28: Введение в Clojure (Никита Прокопов)

# Vector

v

Page 29: Введение в Clojure (Никита Прокопов)

# Vector

v

Page 30: Введение в Clojure (Никита Прокопов)

# Vector

v

Page 31: Введение в Clojure (Никита Прокопов)

# Vector

v

Page 32: Введение в Clojure (Никита Прокопов)

# Vector

v

Page 33: Введение в Clojure (Никита Прокопов)

# Vector

v

Page 34: Введение в Clojure (Никита Прокопов)

# Vector

v

......

Page 35: Введение в Clojure (Никита Прокопов)

# Vector

v

......

up to 32 elms

log32 (s

ize)

Page 36: Введение в Clojure (Никита Прокопов)

# Vector

v

......

up to 32 elms

log32 (s

ize)

00[00000][00000][00000][00000][00001][00100]

Page 37: Введение в Clojure (Никита Прокопов)

# Map## Hash trie

Page 38: Введение в Clojure (Никита Прокопов)

# Map

Page 39: Введение в Clojure (Никита Прокопов)

# 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...

Page 40: Введение в Clojure (Никита Прокопов)

# Atoms

1

x

Page 41: Введение в Clojure (Никита Прокопов)

# Atoms

1 2

x

(f 1)

Page 42: Введение в Clojure (Никита Прокопов)

# Atoms

1 2

x

swap!

Page 43: Введение в Clojure (Никита Прокопов)

# Atoms

1 2

x

Page 44: Введение в Clojure (Никита Прокопов)

# Atoms

1 2 3

x

(f 2)

Page 45: Введение в Clojure (Никита Прокопов)

# Atoms

1 2 3

x

swap!

Page 46: Введение в Clojure (Никита Прокопов)

# Atoms

1 2 3

x

Page 47: Введение в Clojure (Никита Прокопов)

# Atoms

1 2 3

x@x

Page 48: Введение в Clojure (Никита Прокопов)

# Atoms

1 2 3

x

(f (f 1))

@x

Page 49: Введение в Clojure (Никита Прокопов)

# Atoms

Для «простого» mutable stateЯвно выделенная «мутация»Атомарное изменениеЛюбое значение — это всегда результат последовательного применения функций

Page 50: Введение в Clojure (Никита Прокопов)

# Atoms## Конфликты

1 2 3

x

(f 2)

−2

Page 51: Введение в Clojure (Никита Прокопов)

1 2 3

x

(f −2)−2 −1

# Atoms## Конфликты

Page 52: Введение в Clojure (Никита Прокопов)

1 2 3

x

swap!−2 −1

# Atoms## Конфликты

Page 53: Введение в Clojure (Никита Прокопов)

# 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>

Page 54: Введение в Clojure (Никита Прокопов)

# Agent

2

gf

h

thread pool

Page 55: Введение в Clojure (Никита Прокопов)

# Agent

2

hgf

thread pool

Page 56: Введение в Clojure (Никита Прокопов)

# Agent

2

hg

thread pool

f

Page 57: Введение в Clojure (Никита Прокопов)

# Agent

2

hg

thread pool

f

(f 2)

Page 58: Введение в Clojure (Никита Прокопов)

# Agent

3

hg

thread pool

(f 2)

Page 59: Введение в Clojure (Никита Прокопов)

# Agent

3

hg

thread pool

Page 60: Введение в Clojure (Никита Прокопов)

# Agent

3

h

thread pool

g

Page 61: Введение в Clojure (Никита Прокопов)

# Agent

Unit of workПохож на atoms, только…Для последовательных операций:heavy lifting, сохранение в файл, запись в сеть,

конечные автоматы, … Выполняется в отдельном потокеОчередь сообщенийВсегда наблюдаемое состояние

Page 62: Введение в Clojure (Никита Прокопов)

# STM

Согласованное изменение состоянияПроще рассуждатьСложнее ошибитьсяComposableАгенты работают с STM!

Page 63: Введение в Clojure (Никита Прокопов)

# STM

Page 64: Введение в Clojure (Никита Прокопов)

# Concurrency

ИммутабельностьПерсистентные структуры данныхSoftware transactional memoryLock-free

ComposableБезопасно!

Page 65: Введение в Clojure (Никита Прокопов)

# mainstreamless## Clojure 00

Никита Прокоповtonsky.livejournal.com

6 марта 2013