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

Preview:

Citation preview

# 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