SlideShare a Scribd company logo
1 of 82
Download to read offline
Clojure #2
Ugly way for binding coll 
Удобно ли так писать? 
(let [a (nth coll 0) 
b (nth coll 1) 
c (nth coll 2)] 
(doSmth ...))
Destructuring! 
Что-то очень похожее на pattern matching: 
(let [[a b c] coll] 
(doSmth ...))
tail 
Мы уже видели пример ранее: 
(let [[a b & tail] coll] 
(doSmth ...))
maps destructuring 
Для maps это тоже возможно: 
(def my-map {"Clojure" :lang}) 
(let [{lang :lang} my-map] 
(doSmth ...))
Strings 
Destructuring доступен и для строк: 
(defn foo [[a & tail]] 
(= (clojure.string/upper-case a) 
(str a)))
:as keyword 
Иногда саму коллекцию тоже хочется иметь 
в арсенале, тогда на помощь приходит :as 
(defn [[head & tail :as coll]] 
(doSomth ...))
destructuring everywhere 
defn, fn и let - это там, где это доступно. 
Но из-за того, что многое приводится 
макросами к этим конструкциям, 
destructuring доступен очень много где.
Java compatibility
Calling methods 
Это крайне просто: 
(.methodName object) 
(.toLowerCase "AbC") 
; "abc"
Methods with args 
(.methodName object args) 
(.equals "a" "b")
java.lang.Class 
Символ ссылающийся на имя класса также 
дает нам и сам класс (compare .class, classOf) 
(map #(.getName %) 
(.getMethods Boolean))
static things 
Static field: 
(Math/PI) 
Static method: 
(ClassName/methodName args) 
(Thread/activeCount) ; 1
Getting all together 
Наконец-то классический HelloWorld! 
(.println (System/out) 
"Hello, World!")
Operator . 
Есть и альтернатива всему этому… 
(.toUpperCase "abc") 
(. "abc" toUpperCase) 
(Thread/activeCount) 
(. Thread activeCount) 
(.equals "a" "b") 
(. "a" equals "b")
Operator .. 
Последовательные вызовы можно 
объединить: 
(. (. System out) println 
"Hello, World!") 
(.. System out 
(println "Hello, World!"))
operator new 
Есть старый добрый оператор: 
(new ClassName args) 
(new Object) 
(new String "text") 
(new java.util.HashMap)
dot syntax 
Но есть и альтернатива… 
(ClassName. args) 
(Object.) 
(String. "text") 
(java.util.HashMap.)
for example 
(let [h (java.util.HashMap.)] 
(.put h "a" "b") 
(.get h "a"))
import 
Есть и возможность импортировать имена: 
(import [java.util HashMap 
ArrayList]) 
(HashMap.) 
(ArrayList.)
operator doto 
Что делает этот оператор? 
(doto (HashMap.) 
(.put 1 "one") 
(.put 2 "two"))
instance? 
Аналог instanceof/isInstanceOf 
(instance? HashSet (HashSet.))
Java classes in Clojure
reify 
С помощью этого оператора можно 
создавать анонимные классы: 
(reify 
InterfaceName 
(methodName [this args] 
body))
reify 
А также для нескольких интерфейсов: 
(reify 
InterfaceName 
(methodName [this args] 
body) 
AnotherInterface 
(method-2 [this args] body-2))
Runnable 
(def runnable 
(reify Runnable 
(run [this] 
(println "text")))) 
(.start (Thread. runnable))
Array compatibility 
(make-array (Integer/TYPE) 4) 
(make-array String 3) 
(to-array [1 2 3]) 
;untyped: java.lang.Object[] 
(into-array [1 2 3]) 
;typed: java.lang.Long[]
Declaring class in Clojure
gen-class 
Класс объявить легко: 
(gen-class 
:name my.class.Name) 
(compile 'my.class) 
(my.className.)
:methods 
Объявить: 
:methods [[methodName 
[String] String]] 
И реализовать: 
(defn -methodName 
[arg] (str "x " arg))
:prefix 
Можно добавить префикс для понятности: 
:prefix prefix 
Тогда реализовать: 
(defn prefix-methodName 
[arg] (str "x " arg))
:init/:constructors 
Объявить имя для конструктора, и 
сигнатуры конструкторов: 
:init init 
:constructors [[String] [] 
[String String] [String]]
:state 
При создании класса можно записать 
некоторый state, который можно вернуть 
как [[super-call] state] из конструктора. 
Вызывать можно так: 
:state state 
(.state this)
:implements/:extends 
Указать супер класс: 
:extends ClassName 
Можно также объявить список интерфейсов: 
:implements [java.io.Serializable]
:gen-class 
Желательно все это использовать в макросе 
ns, где и указать все, что требуется: 
(ns my.namespace 
(:gen-class))
Polymorphism
Example 
(def circle {:type ::circle :r 10}) 
(def rect {:type ::rectangle :w 10 :h 20}) 
(defn area [{type :type :as shape}] 
(cond 
(= type ::circle) 
(* Math/PI (:r shape) (:r shape)) 
(= type ::rectangle) 
(* (:w shape) (:h shape))))
solution: multimethods 
● Runtime polymorphism 
● Позволяет dispatching по совершенно 
любому объекту
defmulti 
Объявление очень простое: 
(defmulti function-name 
"Doc string" 
dispatch-fn)
defmethod 
За объявлением следуют реализации: 
(defmethod fName1 
match-1 
[this] ...) 
(defmethod fName2 
match-2 
[this] ...)
our example 
(defmulti area :type) 
(defmethod area ::circle [circle] 
(* Math/PI (:r circle) (:r circle))) 
(defmethod area ::rectangle [rect] 
(* (:w rect) (:h rect)))
juxt 
Может возникнуть вопрос, как диспатчится 
по нескольким параметрам. В этом нам 
помогает метод juxt: 
((juxt + - * /) 1 2) 
; [3 -1 2 1/2]
triangle 
Тем самым можем написать следующее: 
(defmulti triangle-type (juxt :type unique-sides)) 
(defmethod triangle-type [::triangle 1] [_] 
:equilateral) 
(defmethod triangle-type [::triangle 2] [_] 
:isosceles) 
(defmethod triangle-type [::triangle 3] [_] 
:scalene)
derive 
Иногда не хочеться писать несколько 
реализаций одного и того же, тогда можно 
использовать derive: 
(derive ::square ::rectangle) 
Теперь можно не писать реализацию area 
для ::square.
:default 
Также можно определить, что делать если 
получили что-то не то (а не просто кидать 
исключение): 
(defmethod triangle-type :default [_] 
:unknown)
factorial homework 
Давайте напишем factorial, используя 
multimethods.
Protocols
defprotocol 
По сути объявляем новый интерфейс (в 
реальности подобный интерфейс и правда 
появляется): 
(defprotocol P 
"doc string" 
(method1 [a] "doc") 
(method2 [a] [a b] "doc2")
Shape 
(defprotocol Shape 
(area [shape]) 
(perimeter [shape])
extend 
(extend Shape 
Rectangle 
{:area (fn [shape] 
(* (:w shape) (:h shape)))} 
{:perimeter (fn [shape] 
(* 2 (+ (:w shape) 
(:h shape))))})
extend-protocol 
(extend-protocol Shape 
Rectangle 
(area [rect] ...) 
(perimeter [rect] ...) 
Circle 
(area [rect] ...) 
(perimeter [rect] ...))
extend-type 
Можно расширять несколько протоколов: 
(extend-type Rectangle 
Shape 
(area [rect] ...) 
(perimeter [rect] ...) 
Drawable 
(draw [rect] ...))
reify 
Аналогично анонимным классам, 
анонимные протоколы: 
(reify Shape 
(area [rectangle] ...) 
(perimeter [rectangle] ...)
defrecord 
Это уже некая реализация в виде класса: 
(defrecord Parallelogram [h b] 
Shape 
(area [p] (* (.b p) (.h p))) 
(perimeter [p] ...))
Concurrency
Starting a thread 
Это очень просто, делается также, как и в 
Java: 
(.start 
(Thread. (fn [] ...))
ExecutorPool 
(let [pool (Executors/newFixedThreadPool 16) 
callable (cast Callable (fn [] 
(reduce + (range 0 10000)))) 
task (.submit pool callable)] 
(.get task))
atoms 
Полезны, чтобы управлять shared memory 
синхронно. 
(def a (atom {}))
deref 
Вычисляет значение атома: 
(deref my-atom) 
Есть и альтернативный синтаксис, более 
короткий: 
@my-atom
swap! 
Все изменения атомов должны быть без 
side-effects, потому что они могут быть 
вычислены несколько раз. Заменяет atom на 
применение функции к аргументам. 
(swap! my-atom fn args)
reset! 
Устанавливает новое значение атома: 
(reset! my-atom new-value)
refs 
Синхронная память, управляемая через 
транзакции: 
(ref [])
dosync 
Этот метод запускает транзакцию. 
Транзакция будет либо целиком выполнена, 
либо целиком невыполнена. Может 
вычисляться несколько раз. 
(let [my-ref (ref false)] 
(dosync (ref-set ref true))
ref-set 
Просто устанавливает значение в 
переменной
alter 
Действует, почти как swap!. 
(alter! my-ref fun args) 
(apply fun my-ref-value args)
ensure 
Гарантирует, что переменная не будет 
изменена в другой транзакции.
commute 
Исполняет функцию над значением ссылки 
и присваивает ссылке. 
Исполняется более конкурентно, чем alter, 
поэтому требует от функции быть 
коммутативной.
agent 
Позволяет стартовать агента, который будет 
исполнять задания асинхронно.
send 
Позволяет отправить агенту задание на 
изменение значения. 
(def my-agent (agent 100)) 
(send my-agent + 100) 
@my-agent 
; 200 
Агенты также интегрированы с STM. send в 
транзакции действует как и alter.
future 
Похоже на агента, только исполняется с 
помощью java.util.concrrent.Future 
(def ft (future 
(reduce + (range 0 10000)))) 
(realized? ft) ;true 
@ft ;49995000
locking 
Позволяет удержать lock на каком-нибудь 
объекте: 
(let [a (java.util.ArrayList.)] 
(locking a 
(.add a 10))) 
Помогает в тех случаях, когда нужна 
совместимость с Java кодом.
bank account homework 
Давайте напишем transfer денег с одного 
банковского аккаунта на другой.
Macros
macros 
Позволяет исполнить код на этапе 
компиляции. Макро-функции могут 
изменить дерево программы, тем самым, мы 
можем изменять синтаксис языка. 
(defmacro call [sym & params] 
(cons sym params)) 
(call + 1 2 3)
unquote 
Можно новое дерево не составлять вручную, 
как в предыдущем примере, а собрать с 
помощью unquote: 
(defmacro twice 
[form] 
`(do 
~form 
~form))
splice-unquote 
Можно список разобрать поэлементно: 
(defmacro my-macro 
[sym forms] 
`(~sym ~@forms))
gensym 
Иногда в макросе хотим создать новую 
переменную, но не всегда мы хотим дать ей 
разумное имя, которое может пересекаться с 
чем-то еще: 
(defmacro f 
[t] 
`(let [z# ~t]))
unquote symbol 
Можем задать новый символ, который будет 
виден магическим образом в коде 
(defmacro with-a 
[& body] 
`(let [~'a 2] 
~@body)) 
(with-a (println a))
macroexpand 
Метод, с которым можно дебажить макросы. 
(defmacro with-a 
[& body] 
`(println ~body)) 
(macroexpand '(with-a 123)) 
; (clojure.core/println (123))
macroexpand-1 
Предыдущий метод повторяет этот, пока это 
имеет смысл, а этот метод раскрывает 
макрос той формы, которую ему передали, 
но не раскрывает подформы. 
Для этого есть macroexpand-all.
or homework 
Давайте напишем свою реализацию or: 
(defmacro my-or 
([] nil) 
([x] x) 
([x & next] 
...))
let homework 
А теперь let, через анонимную функцию: 
(defmacro my-let 
[bindings & body] 
... 
)

More Related Content

What's hot

Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Mikhail Kurnosov
 
DevConf. Дмитрий Сошников - ECMAScript 6
DevConf. Дмитрий Сошников - ECMAScript 6DevConf. Дмитрий Сошников - ECMAScript 6
DevConf. Дмитрий Сошников - ECMAScript 6
Dmitry Soshnikov
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Dima Dzuba
 

What's hot (20)

Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
 
Charming python sc2-8
Charming python sc2-8Charming python sc2-8
Charming python sc2-8
 
8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
DevConf. Дмитрий Сошников - ECMAScript 6
DevConf. Дмитрий Сошников - ECMAScript 6DevConf. Дмитрий Сошников - ECMAScript 6
DevConf. Дмитрий Сошников - ECMAScript 6
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
 
Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
 
Python&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.by
 
Ecma script 6 yevhen diachenko
Ecma script 6 yevhen diachenkoEcma script 6 yevhen diachenko
Ecma script 6 yevhen diachenko
 
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование
 
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
 
Something about Golang
Something about GolangSomething about Golang
Something about Golang
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
 
хитрости выведения типов
хитрости выведения типовхитрости выведения типов
хитрости выведения типов
 

Viewers also liked

Александр Жарков — Эволюция команды разработки: взгляд изнутри
Александр Жарков — Эволюция команды разработки: взгляд изнутриАлександр Жарков — Эволюция команды разработки: взгляд изнутри
Александр Жарков — Эволюция команды разработки: взгляд изнутри
Daria Oreshkina
 
Валкин, Мокевнин — Развитие IT-среды в Ульяновске
Валкин, Мокевнин — Развитие IT-среды в УльяновскеВалкин, Мокевнин — Развитие IT-среды в Ульяновске
Валкин, Мокевнин — Развитие IT-среды в Ульяновске
Daria Oreshkina
 
Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013
ScalaNsk
 
Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)
Alexander Podkhalyuzin
 

Viewers also liked (20)

PiterPy 2015 - Трансдюсеры и Python
PiterPy 2015 - Трансдюсеры и PythonPiterPy 2015 - Трансдюсеры и Python
PiterPy 2015 - Трансдюсеры и Python
 
JSLab. Максим Климишин. "Трансдюсеры, CSP каналы, неизменяемые структуры данных"
JSLab. Максим Климишин. "Трансдюсеры, CSP каналы, неизменяемые структуры данных"JSLab. Максим Климишин. "Трансдюсеры, CSP каналы, неизменяемые структуры данных"
JSLab. Максим Климишин. "Трансдюсеры, CSP каналы, неизменяемые структуры данных"
 
Транзакционная память (on Russian)
Транзакционная память (on Russian)Транзакционная память (on Russian)
Транзакционная память (on Russian)
 
Александр Жарков — Эволюция команды разработки: взгляд изнутри
Александр Жарков — Эволюция команды разработки: взгляд изнутриАлександр Жарков — Эволюция команды разработки: взгляд изнутри
Александр Жарков — Эволюция команды разработки: взгляд изнутри
 
Валкин, Мокевнин — Развитие IT-среды в Ульяновске
Валкин, Мокевнин — Развитие IT-среды в УльяновскеВалкин, Мокевнин — Развитие IT-среды в Ульяновске
Валкин, Мокевнин — Развитие IT-среды в Ульяновске
 
Scala plugin for IntelliJ IDEA
Scala plugin for IntelliJ IDEAScala plugin for IntelliJ IDEA
Scala plugin for IntelliJ IDEA
 
Scala для всех (РИФ 2015)
Scala для всех (РИФ 2015)Scala для всех (РИФ 2015)
Scala для всех (РИФ 2015)
 
Scala training
Scala trainingScala training
Scala training
 
Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013
 
Backend: Пишем на Scala для браузера
Backend: Пишем на Scala для браузераBackend: Пишем на Scala для браузера
Backend: Пишем на Scala для браузера
 
Scala magic
Scala magicScala magic
Scala magic
 
Scala #3
Scala #3Scala #3
Scala #3
 
Scala #4
Scala #4Scala #4
Scala #4
 
Feature suggester
Feature suggesterFeature suggester
Feature suggester
 
Scala #2
Scala #2Scala #2
Scala #2
 
Under the hood of scala implicits (Scala eXchange 2014)
Under the hood of scala implicits (Scala eXchange 2014)Under the hood of scala implicits (Scala eXchange 2014)
Under the hood of scala implicits (Scala eXchange 2014)
 
Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)
 
Lec 2
Lec 2Lec 2
Lec 2
 
Erlang
ErlangErlang
Erlang
 
Scala #5
Scala #5Scala #5
Scala #5
 

Similar to Clojure #2 (2014)

Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)
Ontico
 
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
ScalaNsk
 
Groovy On Grails
Groovy On GrailsGroovy On Grails
Groovy On Grails
guest32215a
 

Similar to Clojure #2 (2014) (20)

Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)
 
Groovy presentation.
Groovy presentation.Groovy presentation.
Groovy presentation.
 
Cpp0x Introduction
Cpp0x IntroductionCpp0x Introduction
Cpp0x Introduction
 
DSLs in Lisp and Clojure
DSLs in Lisp and ClojureDSLs in Lisp and Clojure
DSLs in Lisp and Clojure
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?
 
Суперсилы Chrome developer tools
Суперсилы Chrome developer toolsСуперсилы Chrome developer tools
Суперсилы Chrome developer tools
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
 
Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.
 
Введение в Clojure (Никита Прокопов)
Введение в Clojure (Никита Прокопов)Введение в Clojure (Никита Прокопов)
Введение в Clojure (Никита Прокопов)
 
Scala on android
Scala on androidScala on android
Scala on android
 
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
 
Groovy On Grails
Groovy On GrailsGroovy On Grails
Groovy On Grails
 
Систематизация экспрешнов в IE
Систематизация экспрешнов в IEСистематизация экспрешнов в IE
Систематизация экспрешнов в IE
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
 
implementation of 'go'-like language constructions in scala (russian)
implementation of 'go'-like language constructions in scala (russian)implementation of 'go'-like language constructions in scala (russian)
implementation of 'go'-like language constructions in scala (russian)
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
 
Введение в Clojure (Margincon 2010)
Введение в Clojure (Margincon 2010)Введение в Clojure (Margincon 2010)
Введение в Clojure (Margincon 2010)
 

Clojure #2 (2014)

  • 2. Ugly way for binding coll Удобно ли так писать? (let [a (nth coll 0) b (nth coll 1) c (nth coll 2)] (doSmth ...))
  • 3. Destructuring! Что-то очень похожее на pattern matching: (let [[a b c] coll] (doSmth ...))
  • 4. tail Мы уже видели пример ранее: (let [[a b & tail] coll] (doSmth ...))
  • 5. maps destructuring Для maps это тоже возможно: (def my-map {"Clojure" :lang}) (let [{lang :lang} my-map] (doSmth ...))
  • 6. Strings Destructuring доступен и для строк: (defn foo [[a & tail]] (= (clojure.string/upper-case a) (str a)))
  • 7. :as keyword Иногда саму коллекцию тоже хочется иметь в арсенале, тогда на помощь приходит :as (defn [[head & tail :as coll]] (doSomth ...))
  • 8. destructuring everywhere defn, fn и let - это там, где это доступно. Но из-за того, что многое приводится макросами к этим конструкциям, destructuring доступен очень много где.
  • 10. Calling methods Это крайне просто: (.methodName object) (.toLowerCase "AbC") ; "abc"
  • 11. Methods with args (.methodName object args) (.equals "a" "b")
  • 12. java.lang.Class Символ ссылающийся на имя класса также дает нам и сам класс (compare .class, classOf) (map #(.getName %) (.getMethods Boolean))
  • 13. static things Static field: (Math/PI) Static method: (ClassName/methodName args) (Thread/activeCount) ; 1
  • 14. Getting all together Наконец-то классический HelloWorld! (.println (System/out) "Hello, World!")
  • 15. Operator . Есть и альтернатива всему этому… (.toUpperCase "abc") (. "abc" toUpperCase) (Thread/activeCount) (. Thread activeCount) (.equals "a" "b") (. "a" equals "b")
  • 16. Operator .. Последовательные вызовы можно объединить: (. (. System out) println "Hello, World!") (.. System out (println "Hello, World!"))
  • 17. operator new Есть старый добрый оператор: (new ClassName args) (new Object) (new String "text") (new java.util.HashMap)
  • 18. dot syntax Но есть и альтернатива… (ClassName. args) (Object.) (String. "text") (java.util.HashMap.)
  • 19. for example (let [h (java.util.HashMap.)] (.put h "a" "b") (.get h "a"))
  • 20. import Есть и возможность импортировать имена: (import [java.util HashMap ArrayList]) (HashMap.) (ArrayList.)
  • 21. operator doto Что делает этот оператор? (doto (HashMap.) (.put 1 "one") (.put 2 "two"))
  • 22. instance? Аналог instanceof/isInstanceOf (instance? HashSet (HashSet.))
  • 23. Java classes in Clojure
  • 24. reify С помощью этого оператора можно создавать анонимные классы: (reify InterfaceName (methodName [this args] body))
  • 25. reify А также для нескольких интерфейсов: (reify InterfaceName (methodName [this args] body) AnotherInterface (method-2 [this args] body-2))
  • 26. Runnable (def runnable (reify Runnable (run [this] (println "text")))) (.start (Thread. runnable))
  • 27. Array compatibility (make-array (Integer/TYPE) 4) (make-array String 3) (to-array [1 2 3]) ;untyped: java.lang.Object[] (into-array [1 2 3]) ;typed: java.lang.Long[]
  • 29. gen-class Класс объявить легко: (gen-class :name my.class.Name) (compile 'my.class) (my.className.)
  • 30. :methods Объявить: :methods [[methodName [String] String]] И реализовать: (defn -methodName [arg] (str "x " arg))
  • 31. :prefix Можно добавить префикс для понятности: :prefix prefix Тогда реализовать: (defn prefix-methodName [arg] (str "x " arg))
  • 32. :init/:constructors Объявить имя для конструктора, и сигнатуры конструкторов: :init init :constructors [[String] [] [String String] [String]]
  • 33. :state При создании класса можно записать некоторый state, который можно вернуть как [[super-call] state] из конструктора. Вызывать можно так: :state state (.state this)
  • 34. :implements/:extends Указать супер класс: :extends ClassName Можно также объявить список интерфейсов: :implements [java.io.Serializable]
  • 35. :gen-class Желательно все это использовать в макросе ns, где и указать все, что требуется: (ns my.namespace (:gen-class))
  • 37. Example (def circle {:type ::circle :r 10}) (def rect {:type ::rectangle :w 10 :h 20}) (defn area [{type :type :as shape}] (cond (= type ::circle) (* Math/PI (:r shape) (:r shape)) (= type ::rectangle) (* (:w shape) (:h shape))))
  • 38. solution: multimethods ● Runtime polymorphism ● Позволяет dispatching по совершенно любому объекту
  • 39. defmulti Объявление очень простое: (defmulti function-name "Doc string" dispatch-fn)
  • 40. defmethod За объявлением следуют реализации: (defmethod fName1 match-1 [this] ...) (defmethod fName2 match-2 [this] ...)
  • 41. our example (defmulti area :type) (defmethod area ::circle [circle] (* Math/PI (:r circle) (:r circle))) (defmethod area ::rectangle [rect] (* (:w rect) (:h rect)))
  • 42. juxt Может возникнуть вопрос, как диспатчится по нескольким параметрам. В этом нам помогает метод juxt: ((juxt + - * /) 1 2) ; [3 -1 2 1/2]
  • 43. triangle Тем самым можем написать следующее: (defmulti triangle-type (juxt :type unique-sides)) (defmethod triangle-type [::triangle 1] [_] :equilateral) (defmethod triangle-type [::triangle 2] [_] :isosceles) (defmethod triangle-type [::triangle 3] [_] :scalene)
  • 44. derive Иногда не хочеться писать несколько реализаций одного и того же, тогда можно использовать derive: (derive ::square ::rectangle) Теперь можно не писать реализацию area для ::square.
  • 45. :default Также можно определить, что делать если получили что-то не то (а не просто кидать исключение): (defmethod triangle-type :default [_] :unknown)
  • 46. factorial homework Давайте напишем factorial, используя multimethods.
  • 48. defprotocol По сути объявляем новый интерфейс (в реальности подобный интерфейс и правда появляется): (defprotocol P "doc string" (method1 [a] "doc") (method2 [a] [a b] "doc2")
  • 49. Shape (defprotocol Shape (area [shape]) (perimeter [shape])
  • 50. extend (extend Shape Rectangle {:area (fn [shape] (* (:w shape) (:h shape)))} {:perimeter (fn [shape] (* 2 (+ (:w shape) (:h shape))))})
  • 51. extend-protocol (extend-protocol Shape Rectangle (area [rect] ...) (perimeter [rect] ...) Circle (area [rect] ...) (perimeter [rect] ...))
  • 52. extend-type Можно расширять несколько протоколов: (extend-type Rectangle Shape (area [rect] ...) (perimeter [rect] ...) Drawable (draw [rect] ...))
  • 53. reify Аналогично анонимным классам, анонимные протоколы: (reify Shape (area [rectangle] ...) (perimeter [rectangle] ...)
  • 54. defrecord Это уже некая реализация в виде класса: (defrecord Parallelogram [h b] Shape (area [p] (* (.b p) (.h p))) (perimeter [p] ...))
  • 56. Starting a thread Это очень просто, делается также, как и в Java: (.start (Thread. (fn [] ...))
  • 57. ExecutorPool (let [pool (Executors/newFixedThreadPool 16) callable (cast Callable (fn [] (reduce + (range 0 10000)))) task (.submit pool callable)] (.get task))
  • 58. atoms Полезны, чтобы управлять shared memory синхронно. (def a (atom {}))
  • 59. deref Вычисляет значение атома: (deref my-atom) Есть и альтернативный синтаксис, более короткий: @my-atom
  • 60. swap! Все изменения атомов должны быть без side-effects, потому что они могут быть вычислены несколько раз. Заменяет atom на применение функции к аргументам. (swap! my-atom fn args)
  • 61. reset! Устанавливает новое значение атома: (reset! my-atom new-value)
  • 62. refs Синхронная память, управляемая через транзакции: (ref [])
  • 63. dosync Этот метод запускает транзакцию. Транзакция будет либо целиком выполнена, либо целиком невыполнена. Может вычисляться несколько раз. (let [my-ref (ref false)] (dosync (ref-set ref true))
  • 64. ref-set Просто устанавливает значение в переменной
  • 65. alter Действует, почти как swap!. (alter! my-ref fun args) (apply fun my-ref-value args)
  • 66. ensure Гарантирует, что переменная не будет изменена в другой транзакции.
  • 67. commute Исполняет функцию над значением ссылки и присваивает ссылке. Исполняется более конкурентно, чем alter, поэтому требует от функции быть коммутативной.
  • 68. agent Позволяет стартовать агента, который будет исполнять задания асинхронно.
  • 69. send Позволяет отправить агенту задание на изменение значения. (def my-agent (agent 100)) (send my-agent + 100) @my-agent ; 200 Агенты также интегрированы с STM. send в транзакции действует как и alter.
  • 70. future Похоже на агента, только исполняется с помощью java.util.concrrent.Future (def ft (future (reduce + (range 0 10000)))) (realized? ft) ;true @ft ;49995000
  • 71. locking Позволяет удержать lock на каком-нибудь объекте: (let [a (java.util.ArrayList.)] (locking a (.add a 10))) Помогает в тех случаях, когда нужна совместимость с Java кодом.
  • 72. bank account homework Давайте напишем transfer денег с одного банковского аккаунта на другой.
  • 74. macros Позволяет исполнить код на этапе компиляции. Макро-функции могут изменить дерево программы, тем самым, мы можем изменять синтаксис языка. (defmacro call [sym & params] (cons sym params)) (call + 1 2 3)
  • 75. unquote Можно новое дерево не составлять вручную, как в предыдущем примере, а собрать с помощью unquote: (defmacro twice [form] `(do ~form ~form))
  • 76. splice-unquote Можно список разобрать поэлементно: (defmacro my-macro [sym forms] `(~sym ~@forms))
  • 77. gensym Иногда в макросе хотим создать новую переменную, но не всегда мы хотим дать ей разумное имя, которое может пересекаться с чем-то еще: (defmacro f [t] `(let [z# ~t]))
  • 78. unquote symbol Можем задать новый символ, который будет виден магическим образом в коде (defmacro with-a [& body] `(let [~'a 2] ~@body)) (with-a (println a))
  • 79. macroexpand Метод, с которым можно дебажить макросы. (defmacro with-a [& body] `(println ~body)) (macroexpand '(with-a 123)) ; (clojure.core/println (123))
  • 80. macroexpand-1 Предыдущий метод повторяет этот, пока это имеет смысл, а этот метод раскрывает макрос той формы, которую ему передали, но не раскрывает подформы. Для этого есть macroexpand-all.
  • 81. or homework Давайте напишем свою реализацию or: (defmacro my-or ([] nil) ([x] x) ([x & next] ...))
  • 82. let homework А теперь let, через анонимную функцию: (defmacro my-let [bindings & body] ... )