clojure: lisp for the modern world (русская версия)

34
CLOJURE LISP FOR THE MODERN WORLD Alex Ott [email protected] , http://alexott.net/

Upload: alex-ott

Post on 13-Dec-2014

3.137 views

Category:

Education


2 download

DESCRIPTION

Слайды с презентации о Clojure, которая была дана в рамках конференции ITSea 2012

TRANSCRIPT

Page 1: Clojure: Lisp for the modern world (русская версия)

CLOJURELISP FOR THE MODERN WORLD

Alex [email protected], http://alexott.net/

Page 2: Clojure: Lisp for the modern world (русская версия)

О чем пойдет речь?

Что такое Clojure? Основы языка

Базовый синтаксис Метапрограммирование Полиморфизм Конкурентное программирование

Clojure в реальной жизни Clojure для веб-разработки

Page 3: Clojure: Lisp for the modern world (русская версия)

Что такое Clojure?

Функциональный (неизменяемые данные, ФВП, …)

Lisp-ообразный Конкурентное программирование Многоплатформенный (JVM, .Net, JavaScript,

etc.) Открытый исходный код и либеральная

лицензия Активное сообщество разработчиков Коммерческое применение Коммерческая поддержка

Page 4: Clojure: Lisp for the modern world (русская версия)

Почему ФП?

Неизменяемость данных Отсутствие побочных эффектов Функции в математическом смысле Функции – объекты первого порядка Возможность автоматической

параллелизации кода Меньше проблем с конкурентным

выполнением кода

Page 5: Clojure: Lisp for the modern world (русская версия)

Почему Lisp?

Простой синтаксис - code as data structures (Homoiconic)

Метапрограммирование (макросы) Создание доменно-специфических языков Генерация кода во время компиляции Возможность избежать повторений

Генерация и выполнение кода в runtime

Интерактивная разработка Динамически типизированный

Page 6: Clojure: Lisp for the modern world (русская версия)

Отличия от других Lisp’ов

Немного упрощенный синтаксис -- меньше скобочек

Неизменяемые данные Добавлено больше базовых структур

данных: вектора, отображения (maps) и т.п. Расширяемый reader, но без reader macros "Ленивые" коллекции Мета-информация привязанная к данным и

функциям Case-sensitive names Исключения вместо условий/рестартов

Page 7: Clojure: Lisp for the modern world (русская версия)

Базовый синтаксис

Код – структуры данных Выражение – список, первый элемент

бывает: Функция Макрос Специальная форма

Примеры:(def a 1)

(+ 1 2)

(defn func [x] (* x x))

(defmacro when [x & body]

`(if ~x (do ~@body)))

Page 8: Clojure: Lisp for the modern world (русская версия)

Как выполняется код

Page 9: Clojure: Lisp for the modern world (русская версия)

Базовые типы данных

Числа (целые, рациональные, вещественные): 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"})

Page 10: Clojure: Lisp for the modern world (русская версия)

Коллекции

Разные коллекции: Списки: (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

Page 11: Clojure: Lisp for the modern world (русская версия)

Persistent collections

Новая копия данных при изменении

Затрагивается только измененная часть

Производительность сравнима с коллекциями Java

Page 12: Clojure: Lisp for the modern world (русская версия)

Последовательности

Последовательности (sequences): Коллекции Clojure & Java, массивы,

iterable, … "Ленивые" операции над

последовательностями Могут быть бесконечными Один набор операций над

последовательностями: map, reduce, filter, …

Page 13: Clojure: Lisp for the modern world (русская версия)

Управляющие структуры

Определение переменной: (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

Page 14: Clojure: Lisp for the modern world (русская версия)

Метапрограммирование и макросы

Макросы – функции, выполняемые во время компиляции

Макросы получают код и возвращают новый код

Генерация кода: Стандартные функции работы со

списками Quasi-quote (`) и операторы подстановки: ~ и ~@

Суффикс # для генерации уникальных имен

macroexpand-1 & macroexpand для отладки

Большая часть библиотеки Clojure – макросы

Page 15: Clojure: Lisp for the modern world (русская версия)

Макросы: примеры

Макрос (любой из двух):(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)))

Page 16: Clojure: Lisp for the modern world (русская версия)

Полиморфизм: мультиметоды CLOS-подобный полиморфизм Диспатчеризация в зависимости от

любого условия и количества аргументов

Диспатчеризация выполняется функцией

Диспатчеризация во время выполнения

Возможность построения иерархических зависимостей между типами

Page 17: Clojure: Lisp for the modern world (русская версия)

Мультиметоды: примеры

Определение:(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!”

Page 18: Clojure: Lisp for the modern world (русская версия)

Мультиметоды: примеры

(defmulti encounter

(fn [x y] [(:Species x) (:Species y)]))

(defmethod encounter [:Bunny :Lion] [b l] :run-away)

(defmethod encounter [:Lion :Bunny] [l b] :eat)

(defmethod encounter [:Lion :Lion] [l1 l2] :fight)

(defmethod encounter [:Bunny :Bunny] [b1 b2] :mate)

(def b1 {:Species :Bunny})

(def b2 {:Species :Bunny})

(def l1 {:Species :Lion})

(def l2 {:Species :Lion})

(encounter b1 b2) ==> :mate

(encounter b1 l1) ==> :run-away

(encounter l1 b1) ==> :eat

(encounter l1 l2) ==> :fight

Page 19: Clojure: Lisp for the modern world (русская версия)

Полиморфизм: протоколы

Способ решения expression problem Диспатчеризация только по типу данных Быстрее чем мультиметоды defprotocol: определяет протокол deftype: новые типы данных

(низкоуровневый) defrecord: новые типы данных (только

данные) Можно реализовать протокол для

произвольных классов или интерфейсов (extend-protocol & extend-type)

Page 20: Clojure: Lisp for the modern world (русская версия)

Протоколы: примеры

(defprotocol Hello "Test of protocol"

(hello [this] "hello function"))

(defrecord B [name] Hello

(hello [this] (str "Hello " (:name this) "!")))

(hello (B. "User")) => "Hello User!"

(extend-protocol Hello String

(hello [this] (str "Hello " this "!")))

(hello "world") => "Hello world!"

(extend-protocol Hello java.lang.Object

(hello [this] (str "Hello '" this "'! ("

(type this) ")")))

(hello 1) => "Hello '1'! (class java.lang.Integer)”

Page 21: Clojure: Lisp for the modern world (русская версия)

Concurrency: пространство и время

Clojure разделяет концепции состояния (state) и имени (identity)

Состояние (значение) не изменяется! Identity просто указывает на новое состояние

Page 22: Clojure: Lisp for the modern world (русская версия)

Конкурентное программирование

Средства для изменяемых данных: Ссылки (refs): синхронное,

координированное изменение (STM) Агенты: асинхронное,

некоординированное изменение Атомы: синхронное,

некоординированное изменение Vars: thread-local изменение

@ или deref для доступа к данным Валидаторы и функции-наблюдатели

Page 23: Clojure: Lisp for the modern world (русская версия)

Конкурентное программирование

Параллельное выполнение кода: future pmap, pvalues, pcalls потоки JVM

Синхронизация: promise Отложенное выполнение кода: delay Конкурентные примитивы из JVM

Page 24: Clojure: Lisp for the modern world (русская версия)

Сoncurrency: примеры

(defn acc-validator [new]

(if (neg? (:amount new))

(throw (Exception. "Not money on account!"))

true))

(defn make-account [name init-amount]

(let [r (ref {:name name :amount init-amount})]

(set-validator! r acc-validator) r))

(def acc1 (make-account "User1" 1000))

(def acc2 (make-account "User2" 300))

(defn money-transfer [from to amount]

(dosync (alter from update-in [:amount] - amount)

(alter to update-in [:amount] + amount)))

(money-transfer acc1 acc2 100) => acc1 = 900, acc2 = 400

(money-transfer acc1 acc2 1000) => Exception “No money”

Page 25: Clojure: Lisp for the modern world (русская версия)

Взаимодействие с платформой Взаимодействие с платформой:

Создание объектов: (Class.) или (new Class)

Вызов методов или доступ к членам классов:

`.’, `..’ или doto Генерация классов и интерфейсов

Вызов Clojure кода из Java, и т.п. Примитивы для работы с массивами Генерация и перехват исключений

Page 26: Clojure: Lisp for the modern world (русская версия)

Interoperability: примеры

Создание объектов:(new java.util.Date) <==> (java.util.Date.)

Вызов методов:(.substring "Hello World" 0 5) => "Hello"

(. "Hello World" substring 0 5) => "Hello"

Math/PI => 3.141592653589793

(Integer/parseInt "42") => 42

Clj: (.. System getProperties (get "os.name"))Java: System.getProperties().get("os.name")(doto (java.util.HashMap.)

(.put "a" 1) (.put "b" 2))

Page 27: Clojure: Lisp for the modern world (русская версия)

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: самый популярный

Page 28: Clojure: Lisp for the modern world (русская версия)

Библиотеки и репозитории

Простой доступ к библиотекам 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

Page 29: Clojure: Lisp for the modern world (русская версия)

Как все это дело изучать?

Много книг Интерактивные сайты: 4clojure.com,

tryclj.com, himera.herokuapp.com, … Множество видео-лекций Списки рассылки: clojure, clojure-

russian, … Группы пользователей Конференции в США и Европе IRC Clojure/core: поддержка, тренинги, …

Page 30: Clojure: Lisp for the modern world (русская версия)

Webdev: server side

Ring – низкоуровневая основа: Функции-обработчики Объекты request/response Middleware – функции-обертки для

обработчика Более высокоуровневые фреймворки:

Compojure – упрощение разработки с Ring Noir – микрофреймворк на базе Ring

Hiccup – генерация HTML Плугины для Leiningen: lein-ring, lein-noir, … Standalone или war

Page 31: Clojure: Lisp for the modern world (русская версия)

Webdev: server side, примеры

(defroutes app-routes

(GET ["/user/:id", :id #"[0-9]+"] [id]

(get-user-info id))

(GET "/users/" []

(get-user-list))

(GET "/" [] "It works!\n")

(route/resources "/")

(route/not-found "Resource isn't found"))

(def app (-> #'app-routes

wrap-base-url

handler/site

(wrap-reload '[ws])))

Page 32: Clojure: Lisp for the modern world (русская версия)

Webdev: ClojureScript

Подмножество Clojure: Пространства имен Неизменяемые данные ….

Библиотеки из Clojure & JavaScript Производительный Оптимизуется с помощью Google Closure Может выполняться на Node.js Отличия от Clojure:

нет ссылок/транзакций, агентов и vars – только атомы отличия в объявлении пространств имен нет компиляции и вычисления кода в run-time нет Java-специфичных вещей, как gen-class, gen-

interface, …

Page 33: Clojure: Lisp for the modern world (русская версия)

Webdev: deployment

Поддержка развертывания для: Google App Engine Heroku RedHat's OpenShift Elastic Beanstalk

Платформо-специфичные библиотеки Плагины для Leiningen

Page 34: Clojure: Lisp for the modern world (русская версия)

Вопросы

Спасибо за внимание