Scala, SBT & Play! for Rapid Application Development
Clojure: Lisp for the modern world (русская версия)
1. CLOJURE
LISP FOR THE MODERN
WORLD
Alex Ott
alexott@gmail.com, http://alexott.net/
2. О чем пойдет речь?
Что такое Clojure?
Основы языка
Базовый синтаксис
Метапрограммирование
Полиморфизм
Конкурентное программирование
Clojure в реальной жизни
Clojure для веб-разработки
3. Что такое Clojure?
Функциональный (неизменяемые данные, ФВП, …)
Lisp-ообразный
Конкурентное программирование
Многоплатформенный (JVM, .Net, JavaScript, etc.)
Открытый исходный код и либеральная лицензия
Активное сообщество разработчиков
Коммерческое применение
Коммерческая поддержка
4. Почему ФП?
Неизменяемость данных
Отсутствие побочных эффектов
Функции в математическом смысле
Функции – объекты первого порядка
Возможность автоматической параллелизации
кода
Меньше проблем с конкурентным
выполнением кода
5. Почему Lisp?
Простой синтаксис - code as data structures
(Homoiconic)
Метапрограммирование (макросы)
Создание доменно-специфических языков
Генерация кода во время компиляции
Возможность избежать повторений
Генерация и выполнение кода в runtime
Интерактивная разработка
Динамически типизированный
6. Отличия от других Lisp’ов
Немного упрощенный синтаксис -- меньше
скобочек
Неизменяемые данные
Добавлено больше базовых структур данных:
вектора, отображения (maps) и т.п.
Расширяемый reader, но без reader macros
"Ленивые" коллекции
Мета-информация привязанная к данным и
функциям
Case-sensitive names
Исключения вместо условий/рестартов
7. Базовый синтаксис
Код – структуры данных
Выражение – список, первый элемент бывает:
Функция
Макрос
Специальная форма
Примеры:
(def a 1)
(+ 1 2)
(defn func [x] (* x x))
(defmacro when [x & body]
`(if ~x (do ~@body)))
9. Базовые типы данных
Числа (целые, рациональные, вещественные):
42, 1/3, 1N, 4.2, 42.2M
Строки: "String»
Знаки (characters): a, newline, …
Регулярные выражения: #"d+"
Логические значения: true, false
nil – как null в Java
Символ (symbol): name
Keyword: :name, (:name {:name "test"})
10. Коллекции
Разные коллекции:
Списки: (1 2 3 "abc")
Вектора: [1 2 3]
Отображения (maps): {:k1 1234 :k2 "value"}
Множества: #{:val1 "text" 1 2 10}
Persistent & transient коллекции
Вектора, отображения и множества сами являются
функциями:
([1 2 3] 2) => 3
({:a 1 :b 2 :c 3} :b) => 2
11. Persistent collections
Новая копия данных
при изменении
Затрагивается только
измененная часть
Производительность
сравнима с
коллекциями Java
12. Последовательности
Последовательности (sequences):
Коллекции Clojure & Java, массивы, iterable, …
"Ленивые" операции над
последовательностями
Могут быть бесконечными
Один набор операций над
последовательностями: map, reduce, filter, …
13. Управляющие структуры
Определение переменной: (def name value)
Определение функции: (defn name [args…]
body), (fn [args…] body), #(body)
Локальные переменные: (let [name1 value1
name2 value2] body)
Ветвление: if, cond, when, …
Последовательное выполнение: do
Цикл: loop/recur
List comprehension: for
Исключения: try/catch, throw
14. Метапрограммирование и макросы
Макросы – функции, выполняемые во время
компиляции
Макросы получают код и возвращают новый код
Генерация кода:
Стандартные функции работы со списками
Quasi-quote (`) и операторы подстановки: ~ и ~@
Суффикс # для генерации уникальных имен
macroexpand-1 & macroexpand для отладки
Большая часть библиотеки Clojure – макросы
15. Макросы: примеры
Макрос (любой из двух):
(defmacro when [test & body]
(list 'if test (cons 'do body)))
(defmacro when [x & body]
`(if ~x (do ~@body)))
Использование:
(when (pos? a)
(println "positive") (/ b a))
Раскрывается в:
(if (pos? a)
(do (println "positive") (/ b a)))
16. Полиморфизм: мультиметоды
CLOS-подобный полиморфизм
Диспатчеризация в зависимости от любого
условия и количества аргументов
Диспатчеризация выполняется функцией
Диспатчеризация во время выполнения
Возможность построения иерархических
зависимостей между типами
17. Мультиметоды: примеры
Определение:
(defmulti m-example class)
(defmethod m-example String [this]
(println "This is string '" this "'"))
(defmethod m-example java.util.Collection [this]
(print "This is collection!"))
Использование:
(m-example "Hello") => "This is string 'Hello'"
(m-example [1 2 3]) => "This is collection!"
(m-example '(1 2 3)) => "This is collection!”
19. Полиморфизм: протоколы
Способ решения expression problem
Диспатчеризация только по типу данных
Быстрее чем мультиметоды
defprotocol: определяет протокол
deftype: новые типы данных (низкоуровневый)
defrecord: новые типы данных (только данные)
Можно реализовать протокол для произвольных
классов или интерфейсов (extend-protocol &
extend-type)
21. Concurrency: пространство и время
Clojure разделяет
концепции состояния Code Code Code
(state) и имени (past) (present) (future)
(identity)
Состояние (значение) Identity
(ref/agent/atom
name)
не изменяется!
Identity просто
указывает на новое State S1
[1 2 3 4]
State S2
[1 2 3 4 5 6 7]
State S3
[?????]
состояние
22. Конкурентное программирование
Средства для изменяемых данных:
Ссылки (refs): синхронное, координированное
изменение (STM)
Агенты: асинхронное, некоординированное
изменение
Атомы: синхронное, некоординированное
изменение
Vars: thread-local изменение
@ или deref для доступа к данным
Валидаторы и функции-наблюдатели
23. Конкурентное программирование
Параллельное выполнение кода:
future
pmap, pvalues, pcalls
потоки JVM
Синхронизация: promise
Отложенное выполнение кода: delay
Конкурентные примитивы из JVM
25. Взаимодействие с платформой
Взаимодействие с платформой:
Создание объектов: (Class.) или (new Class)
Вызов методов или доступ к членам классов:
`.’, `..’ или doto
Генерация классов и интерфейсов
Вызов Clojure кода из Java, и т.п.
Примитивы для работы с массивами
Генерация и перехват исключений
27. IDE & средства сборки кода
Поддержка в IDE/редакторах:
Eclipse (Counterclocwise)
Netbeans (Enclojure)
IntelliJ IDEA (La Clojure)
Emacs + SLIME или nRepl
VimClojure
Textmate, Sublime Text 2, Jedit
Средства сборки кода:
Поддержка Clojure в Maven, Ant, Cake, Gradle
Leiningen: самый популярный
28. Библиотеки и репозитории
Простой доступ к библиотекам JVM
Библиотеки написанные на Clojure:
Web-разработка: Compojure, Ring, Scriptjure, Noir
RDBMS: ClojureQL, clojure.java.jdbc, Korma
NoSQL: Monger, Clouch, …
Contrib библиотеки: core.*
GUI: Seesaw
Логическое программирование: core.logic
Репозитории: Maven Central, Clojars.org
29. Как все это дело изучать?
Много книг
Интерактивные сайты:
4clojure.com, tryclj.com, himera.herokuapp.com,
…
Множество видео-лекций
Списки рассылки: clojure, clojure-russian, …
Группы пользователей
Конференции в США и Европе
IRC
Clojure/core: поддержка, тренинги, …
30. Webdev: server side
Ring – низкоуровневая основа:
Функции-обработчики
Объекты request/response
Middleware – функции-обертки для обработчика
Более высокоуровневые фреймворки:
Compojure – упрощение разработки с Ring
Noir – микрофреймворк на базе Ring
Hiccup – генерация HTML
Плугины для Leiningen: lein-ring, lein-noir, …
Standalone или war
32. Webdev: ClojureScript
Подмножество Clojure:
Пространства имен
Неизменяемые данные
….
Библиотеки из Clojure & JavaScript
Производительный
Оптимизуется с помощью Google Closure
Может выполняться на Node.js
Отличия от Clojure:
нет ссылок/транзакций, агентов и vars – только атомы
отличия в объявлении пространств имен
нет компиляции и вычисления кода в run-time
нет Java-специфичных вещей, как gen-class, gen-interface, …
33. Webdev: deployment
Поддержка развертывания для:
Google App Engine
Heroku
RedHat's OpenShift
Elastic Beanstalk
Платформо-специфичные библиотеки
Плагины для Leiningen