• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Clojure #1
 

Clojure #1

on

  • 378 views

 

Statistics

Views

Total Views
378
Views on SlideShare
378
Embed Views
0

Actions

Likes
0
Downloads
8
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Clojure #1 Clojure #1 Presentation Transcript

    • Clojure #1 Introduction to clojure
    • Why Clojure? ● ● ● ● ● ● ● For JVM with Java interoperability Instant run/reloading Functional Lisp features (macros, expressive) built-in STM Dynamic Good performance
    • Important tools ● Leiningen - Clojure build tool ● REPL, nREPL ● Editors: IDEA (La Clojure, Cursive), Emacs, Light Table
    • Basics
    • Functions Очень простой синтаксис: (fn [] 4)
    • Function call Любая функция вызывается в prefix нотации: (+ 1 1) В данном случае + это функция, а единицы это аргументы.
    • Expressions В Clojure, как практически и в Scala все является выражением, то есть возвращает значение: (if condition then-branch else-branch)
    • Literals ● "a string" - String ● :key - Keyword ● 'symbol - Symbol ● newline, c - Character ● nil - No value ● true, false - Booleans ● Numbers like in Java
    • Data literals ● [1 2 3] - Vector ● {:key value :key1 value1} - Map ● #{:key :key1} - Set ● #() - Анонимная функция (fn)
    • Definitions Определяет “переменные”: (def x (+ 1 (- 3 1)))
    • Named functions (defn foo "This is documentation" [arguments] body) Параметры анонимных функций определяются также.
    • Higher order functions Можно в качестве параметров передавать и другие функции, например: (map inc [1 2 3]) Или анонимный вариант: (map (fn [i] (+ i 1)) [1 2 3])
    • Scoped definitions (let) Можно определить переменные, которые будут видны лишь внутри s-expr: (def sum-result (let [pi Math/PI] (/ (* pi pi) 6)))
    • Conrol structures
    • if Ранее уже видели, else branch должен обязательно присутствовать
    • do Если нужно выполнить несколько выражений прежде, чем что-то вернуть. Признак side effects: (do expr1 expr2 return-expression)
    • when Всегда возвращает nil. Комбинация if только с then branch и do. (when (even? 2) expr1 expr2)
    • if-let Комбинация let и if с проверкой на nil/false: (def France {:capital "Paris"}) (if-let [capital (:capital France)] (println "Capital is " capital) (println "Capital is empty"))
    • cond Является альтернативой для else-if цепочек: (defn foo [n] (cond (> n 0) "positive" (< n 0) "negative" :else "zero"))
    • More Clojure basics
    • Function composition Следующий код легко может быть переписан: (fn [e] (fn1 (fn2 e))) Короче будет так: (comp fn1 fn2)
    • Function application Есть более длинная форма для вызова функции, ее можно использовать, например, в макросах: (apply + [1 2 3])
    • Namespaces Каждый символ определен в каком-то namespace, его можно задать с помощью вызова ns: (ns mylib.core)
    • :requre С помощью этого ключа можно добавить в namespace элементы из других namespaces: (ns foo (:require clojure.test [clojure.string :as str]))
    • :use Это сочетание :require и :refer. Использовать следует с осторожностью, как пример: (ns foo (:use clojure.string)) WARNING: replace already refers to: #'clojure.core/replace in namespace: foo, being replaced by: #'clojure.string/replace WARNING: reverse already refers to: #'clojure.core/reverse in namespace: foo, being replaced by: #'clojure.string/reverse
    • :only Для того, чтобы избежать подобных проблем, можно использовать ключ :only (ns foo (:use [clojure.string :only [join]]))
    • :import С помощью этого ключа можно добавлять классы из Java: (ns some.foo.space "This is namespace doc" (:import (java.util Date GregorianCalendar)))
    • Clojure data structures
    • Lists Списки определяются так: '(1 2 3) '("Scala" "Kotlin" "Erlang" "Clojure")
    • Vectors Вектора уже ранее определяли, это аналог массивов в Clojure.
    • Sets Множества задаются двумя способами #{1 2 3} (set [1 2 3])
    • Maps Также уже ранее обсуждали: {:id :name 55 "Clojure" :is-dynamic true}
    • Immutability Все структуры данных в Clojure неизменяемы. Чаще всего, вновь создаваемые, структуры данных используют предыдущие версии, но все равно это может быть медленно.
    • Transient Для performance critical single-threaded кусков кода, можно написать все быстрее: (defn vrange [n] (loop [i 0 v (transient [])] (if (< i n) (recur (inc i) (conj! v i)) (persistent! v))))
    • Vectors and Maps basics
    • get Для векторов достает элемент по индексу. Для Maps достает элемент по ключу. (get [1 2 3] 1) ;2 (get {:one 1} :one) ;1 get-in принимает вектор, и выполняет последовательно get (get-in [1 [1 2] 3] [1 1]) ;2
    • assoc Для векторов добавляет новый элемент по индексу (возвращает новый вектор). Для Maps добавляет новую пару key/value (assoc [] 0 1) ;[1] (assoc {} :key :value) ;{:key :value}
    • dissoc Удаляет элемент по ключу в Maps: (dissoc {:key :value} :key) ; {}
    • keys/vals Для Maps мы можем вытащить keys и values: (keys {:a :b :c :d}); (:a :c) (vals {:a :b :c :d}); (:b :d)
    • merge Также можно объединять несколько Maps, перекрывая значения слева направо (merge {:a :x :c :x} {:a :b} {:a :c :e :f}) ; {:a :c :c :x :e :f}
    • merge-with Если мы хотим перекрывать справа налево, то это тоже возможно: (merge-with (fn [a b] a) {:a :x :c :x} {:a :b} {:a :c :e :f}) ; {:a :x :c :x :e :f}
    • All collections basics
    • cons Образуется от слова construct, может добавлять первый элемент к спискам и векторам (cons 1 [1 2]) ; [1 1 2] (cons 1 '(1 2)) ; (1 1 2)
    • conj Добавляет элемент туда, где это удобнее в плане реализации коллекции: (conj [1 2] 1) ; [1 2 1] (conj '(1 2) 1) ; (1 1 2)
    • concat Объединяет две последовательности в один список (concat [1 2] '(3 4)) ; (1 2 3 4)
    • disj Удаляет элемент из множества (и только!) (disj #{:a :b} :a) ; #{:b}
    • seq Превращает любую коллекцию (включая Java collections, arrays) в seq коллекцию. Что важно, пустая коллекция превращается в nil.
    • Advanced collection operations
    • partition Разбивает коллекцию на части определенной длины. Можно указать шаг, тогда части смогут перекрываться: (partition 2 [1 2 3 4 5]) ; ((1 2) (3 4))
    • flatten Собирает одну коллекцию из коллекции коллекций: (flatten [a [b] [c d]]) ; (a b c d)
    • frequencies Возвращает частоту, встречающихся элементов: (frequencies [1 2 3 2 1 2]) ; {1 2, 2 3, 3 1}
    • every? Проверяет, что все элементы удовлетворяют некоторому предикату: (every? even? [2 4 6]) ; true (every? even? [1 2 3]) ; false
    • some true если хотя бы один элемент удовлетворяет предикату: (some even? [2 4 5]) ; true (some even? [1 5 3]) ; nil
    • for comprehensions Создает ленивую коллекцию (for [x (range 2) y (range 2)] [x y]) ; [0 0] [0 1] [1 0] [1 1] (for [x (range 3) :while (even? x)] x) ; [2]
    • doseq Поэтому для side effects нужно использовать doseq, в котором они предполагаются, и функция всегда возвращает nil.