Как Макар начал clojure учить
История о том, как я начал учить clojure
Основы Clojure
Зачем-то решил поизучать clojure. Буду писать заметки про то, что узнал. Возможно в будущем приведу в красивый вид.
Примитивы
- Числа:
- Целые числа
- Вещественные числа
- Рациональьные числа
- Строки
- Символы (
\a
) - Ключевые слова (
:a
)
- Числа:
Коллекции данных
- Векторы - аналогичны массивам:
[1 2 3]
; Добавление нового элемента черезconj
в конец:(conj [1 2 3] 4) => [1 2 3 4]
. Получить элемент можно с помощьюget
:(get [1 2 3] 0) => 1
- Списки - определяется таким образом:
'(1 2 3)
или(list 1 2 3)
; черезconj
добавление элемента происходит в начало -(conj '(1 2 3) 4) => (4 1 2 3)
. Получить элемент с помощьюget
нельзя, нужно пользоватьсяnth
:(nth '(1 2 3) 2) => 3
- Set - набор уникальных значений:
#{1 2 3}
. Создать сет можно используяset
- Ассоциативные массивы:
{:a 1 :b 2}
. Создать можно с помощьюhash-map
:(hash-map :a 2 :b 3) => {:a 2 :b 3}
. Получить элемент можно с помощьюget
или используя keyword:(get {:a 2 :b 3} :b) => 3
или({:a 2 :b 3} :b) => 3
или(:b {:a 2 :b 3}) => 3
- Векторы - аналогичны массивам:
Функции
Определение функции состоит из пяти основных частей:defn
- Имя функции
- docstring - для описания функции (опционально)
- Параметры функции в квадратных скобках
- Тело функции
Например,
(defn greeting <- function name "Return a greeting" <- docstring [name] <- args (str "Hello " name)) <- function body (greeting "Makar") => "Hello Makar"
Есть перегрузка функций, например
(defn some-func ;; 3 args ([first-arg second-arg third-arg] (println first-arg second-arg third-arg)) ;; 2 args ([first-arg second-arg] (println first-arg second-arg)) ;; 1 arg ([first-arg] (println first-arg)))
Чтобы обратиться ко всем оставшимся аргументам функции, используется
&
:(defn some-func [name & rest] <- внутри rest все оставщиеся аргументы (str "Hello, " name ". Do you have " (clojure.string/join " or " rest) "?")) (some-func "Makar" "bread" "vine") => "Hello, Makar. Do you have bread or vine?"
Анонимные функции
Функции не обязаны иметь имя. Есть несколько способов использовать анонимные функции. Первый:
(fn [params]
body)
Использовать можно так:
(map (fn [name] (str "Hello, " name)) ["First", "Second"])
;; => ("Hello, First" "Hello, Second")
Можно записывать анонимную функцию в переменную:
(def custom-square (fn [x] (* x x)))
(custom-square 12) => 144
В clojure есть более короткий способ обьявлять анонимную функцию:
#(* % 2)
(#(* % 2) 2) => 4
Такая запись возможна благодаря макросам, которые существуют в clojure. % - это аргумент, переданный в функцию. Можно использовать %1, %2 и т.д. Если хочется, то можно использовать rest-параметр: %&
Продолжение следует...