fix(guide): simplify directory structure

This commit is contained in:
Mrugesh Mohapatra
2018-10-16 21:26:13 +05:30
parent f989c28c52
commit da0df12ab7
35752 changed files with 0 additions and 317652 deletions

View File

@@ -0,0 +1,16 @@
---
title: Clojure Collections
localeTitle: Коллекции Clojure
---
Одним из главных положительных моментов Clojure является то, что у него есть довольно много разных видов последовательности: векторы, списки, хэшмапы, _о мой!_ И каждый тип коллекций имеет свои собственные преимущества, недостатки и целый ряд полезных функций, которые работают на них.
Чтобы понять различия между каждым типом коллекции, когда использовать каждый из них и как конвертировать между ними все, может потребоваться проверить другие типы коллекции и напомнить себе, что делает их особенными.
Таким образом, эта страница служит индексом, поэтому вы можете легко просмотреть любую из статей о структурах данных.
* [Списки](http://forum.freecodecamp.com/t/clojure-lists-they-are-everything/18417)
* [векторы](http://forum.freecodecamp.com/t/clojure-vectors/18421)
* [HashMaps](http://forum.freecodecamp.com/t/clojure-hashmaps/18414)
| [![:point_left:](/images/emoji/emoji_one/point_left.png?v=2 ": Point_left:") Предыдущая](http://forum.freecodecamp.com/t/clojure-more-on-functions/18413) | [![:book:](/images/emoji/emoji_one/book.png?v=2 ":книга:") Главная ![:book:](/images/emoji/emoji_one/book.png?v=2 ":книга:")](http://forum.freecodecamp.com/t/clojure-resources/18422) | [следующий ![:point_right:](/images/emoji/emoji_one/point_right.png?v=2 ": Point_right:")](http://forum.freecodecamp.com/t/clojure-lists-they-are-everything/18417) |
| [Подробнее о функциях](http://forum.freecodecamp.com/t/clojure-more-on-functions/18413) | [Содержание](http://forum.freecodecamp.com/t/clojure-resources/18422) | [Списки](http://forum.freecodecamp.com/t/clojure-lists-they-are-everything/18417) |

View File

@@ -0,0 +1,141 @@
---
title: Clojure Conditionals
localeTitle: Clojure Conditionals
---
Вы не собираетесь нигде на язык, если все, что вы можете сделать, это определить функции, которые печатают вещи и выполняют простую арифметику. Условные и логические элементы являются фундаментальной частью создания кода, который делает интересные, полезные вещи. Попробуйте представить мир без логики в программах: вы даже не сможете простыми вещами, например, проверить, равны ли два числа!
## Логические операторы
Clojure, как и большинство языков, имеет 3 логических оператора: `and` , и / `or` `not` . Эти функции принимают логические значения ( `true` или `false` ) в качестве аргументов и возвращают логические значения, основанные на том, что эти логические элементы. Как и все в Lisp, эти операторы используют префиксную нотацию, что означает, что они могут выглядеть странно для вас.
```
(and true false)
; => false
(and true true)
; => true
(or false false)
; => false
(or true false)
; => true
(not true)
; => false
(not false)
; => true
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/XfXn8T)
## Если
`if` позволяет выполнить код на основе того, является ли логическое значение `true` или `false` . `if` в Clojure выглядит довольно странно, не потому, что использует префиксную нотацию, а потому, что ключевого слова else нет. Если условие истинно, оно оценивает первое выражение. Если он ложный, он выполняет второй.
```
(if (= (+ 2 2) 4)
(println "Maths works!") ; this gets evaluated if 2 + 2 = 4
(println "UH OH")) ; this gets evaluated if 2 + 2 != 4
; => Maths works!
; nil
```
Это создает проблему: что, если мы хотим сделать несколько вещей?
```
(if (= (+ 2 2) 4)
(println "Maths works!")
(println "Maths still works!")
(println "UH OH"))
; => CompilerException java.lang.RuntimeException: Too many arguments to if
```
К счастью, у нас `do` функция `do` чтобы решить эту проблему. `do` оценку нескольких выражений один за другим.
```
(if (= (+ 2 2) 4)
(do ; all of this gets evaluated if 2 + 2 = 4
(println "Maths works!")
(println "Maths still works!"))
(println "UH OH"))
; => Maths works!
; Maths still works!
; nil
```
**Примечание:** поскольку `if` есть, само выражение, нет необходимости в тройном операторе, например, во многих C-подобных языках.
```
var doesMathsWork = 2 + 2 === 4 ? "Maths works!" : "UH OH";
console.log(doesMathsWork);
// => Maths works!
```
Теперь, когда вы видели, как это работает, это выглядит не так странно? Это гораздо легче читать и понимать ( не обращая внимания на отсутствие слова `else` ):
```
(def does-maths-work (if (= (+ 2 2) 4) "Maths works!" "UH OH"))
(println does-maths-work)
; => Maths works!
; nil
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/5XhcAa)
## Альтернативы if
Clojure также имеет некоторые макросы, которые ведут себя аналогично `if` , и иногда могут быть более краткими.
`if-not` , пожалуй, самый простой пример - это `if` инвертировать. Эти два фрагмента кода абсолютно одинаковы:
```
(def does-maths-work (if (not (= (+ 2 2) 4)) "UH OH" "Maths works!"))
(def does-maths-work (if-not (= (+ 2 2) 4) "UH OH" "Maths works!"))
```
Первое выражение оценивается, если оно ложно, а второе оценивается, если оно истинно. Обратите внимание на то, что использование `if-not` избегает гнездиться наше состояние внутри `not` , что может помочь облегчить наш код , чтобы понять.
`when` это еще один полезный макрос. Эти два фрагмента кода одинаковы:
```
(if (= (+ 2 2) 4) (do (println "Maths works!") (println "Hooray!")))
(when (= (+ 2 2) 4) (println "Maths works!") (println "Hooray!"))
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/tUVAw3)
**Примечание:** Нет, `when/else` . `when` выполняется олько в том_ случае, если условие истинно.
`cond` позволяет объединить множество условий в одно выражение. Он принимает последовательность пар логического выражения и выражения и оценивает каждое логическое выражение по порядку. Когда он находит логическое выражение, которое оценивает значение `true` , он вычисляет второе выражение пары. После этого никакие другие выражения не оцениваются. Это поведение похоже на логику короткого замыкания в Javascript.
```
(cond (= 0 1) "I'm paired with a false expression and I don't evalute.."
(= 1 1) "I'm the first expression paired with a true expression!"
(= 2 2) "I don't evalute even though I'm also paired with true ;_;"
:else "I evaluate if no other boolean expressions evaluate to true")
; => "I'm the first expression paired with a true expression!"
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/zu5RCq)
Ключевое слово `:else` можно использовать вместо логического выражения в последней паре выражений в `cond` . Это означает, что соответствующее выражение должно быть оценено, если все остальные булевские выражения оцениваются как false. Это то же самое, что `true` в качестве последнего булевского выражения.
## Специальные формы и оценка
Возможно, вы заметили, что правила оценки условных выражений немного отличаются от других выражений. Условное выражение является частью группы выражений, называемых _специальными формами_ . Это означает, что они не соответствуют нормальным правилам оценки Clojure.
Как вы теперь знаете, условное выражение оценивает только подвыражение, которое соответствует логическому результату. Это означает, что неверный код в условном выражении не будет оцениваться в некоторых случаях. Рассмотрим приведенные ниже выражения `if` . Хотя `(+ 1 "failure")` является недопустимым выражением, Clojure генерирует исключение только при условии `false` .
```
(if true "sucess" (+ 1 "failure"))
; => "sucess"
(if false "sucess" (+ 1 "failure"))
; => ClassCastException java.lang.String cannot be cast to java.lang.Number ...
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/n4Ug2S)
Сравните это с поведением `my-if` определенным ниже:
```
(defn my-if [condition true-case false-case]
(if condition true-case false-case))
(my-if true "sucess" (+ 1 "failure"))
; => ClassCastException java.lang.String cannot be cast to java.lang.Number ...
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/U7cVI4)
`my-if` - это функция с нормальными правилами оценки, поэтому все ее подвыражения должны быть опровергнуты до того, как их можно будет оценить.
В Clojure есть много полезных макросов, подобных этим для всех видов задач. Попробуйте взглянуть на [документацию Clojure](https://clojuredocs.org/) и посмотреть, сможете ли вы найти ее больше!
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ": Point_left:") Предыдущая](//forum.freecodecamp.com/t/clojure-the-basics/18410) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:") Главная ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [следующий ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ": Point_right:")](//forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415) |
| [Резюме](//forum.freecodecamp.com/t/clojure-the-basics/18410) | [Содержание](//forum.freecodecamp.com/t/clojure-resources/18422) | [Условные](//forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415) |

View File

@@ -0,0 +1,58 @@
---
title: Clojure Create Local Variables with Let
localeTitle: Clojure Создание локальных переменных с Let
---
`let` это фундаментальная часть Clojure. Если `def` создает глобальную переменную, `let` создает локальную переменную.
```
(def x 5)
(println x)
; => 5
; nil
(let [x 2]
(println x))
; => 2
; nil
(println x)
; => 5
; nil
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/xcNth2)
`x` в этом примере никогда не изменяется. `x` просто ссылается на что-то другое внутри нашей привязки `let` . Это может быть полезным способом избежать повторения внутри функции.
Это невероятно полезно. Слишком много глобальных переменных может привести к неприятным ошибкам и непреднамеренному поведению.
```
(def x 5)
(defn add-5 [y] (+ xy))
(add-5 5)
; => 10
(defn change-x []
(def x 6))
(change-x)
; => nil
(add-5 5)
; => 11
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/MFjA3C)
О, о! Это больше не добавляет 5! Конечно, этот пример немного глуп, но использование слишком большого числа глобальных переменных может привести к ошибкам, столь же страшным, как этот.
**Примечание.** Мы не _переназначаем_ здесь `x` , как на языке C. Мы просто создаем новую переменную, которая также называется x. Это _очень, очень, **очень**_ плохая идея.
## Множественные привязки
`let` также может определять сразу несколько переменных и может назначать переменные выражениям.
```
(let [spam "foo"
ham (str "b" "ar")] ; str is a function that concatenates strings
(println spam ham)) ; or converts variables into strings.
; => foo bar
; nil
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/y5EBIM)
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ": Point_left:") Предыдущая](//forum.freecodecamp.com/t/clojure-conditionals/18412) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:") Главная ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [следующий ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ": Point_right:")](//forum.freecodecamp.com/t/clojure-loop-recur/18418) |
| [Условные](//forum.freecodecamp.com/t/clojure-conditionals/18412) | [Содержание](//forum.freecodecamp.com/t/clojure-resources/18422) | [Loop и Recur](//forum.freecodecamp.com/t/clojure-loop-recur/18418) |

View File

@@ -0,0 +1,104 @@
---
title: Clojure Hashmaps
localeTitle: Clojure Hashmaps
---
Хешмап - это коллекция, которая отображает ключи к значениям. У них разные имена на других языках; Python относится к ним как словарям, а объекты Javascript по существу работают как хэшмапы.
Хешмап может, как и многие коллекции, быть построен двумя способами. Существует функция-конструктор:
```
;; Note that each argument is *prepended* to the hashmap, not appended.
(def a-hashmap (hash-map :a 1 :b 2 :c 3))
a-hashmap
; => {:c 3, :b 2, :a 1}
```
Вы также можете определить их, используя литерал hashmap. Это часто более кратким и ясным. Рекомендуется использовать запятые для разделения пар ключ / значение в хэшмапах, так как это может сделать границы более четкими.
```
;; This hashmap is actually in the right order, unlike the one above.
(def another-hashmap {:a 1, :b 2, :c 3})
another-hashmap
; => {:a 1, :b 2, :c 3}
```
## Ключевые слова и извлечение значений из хэшмапов
Задержать. Что это? `:a` ? `:b` ? `:c` ? Они выглядят странно. Вы видите, это ключевые слова. Их называют _ключевыми_ словами, поскольку они часто используются в качестве ключей в хэшмапах.
Почему они часто используются в качестве ключей? Ну, в отличие от строк, ключевые слова могут использоваться как функции для извлечения значений из хэш-карты; нет необходимости в `get` или `nth` !
```
(def string-hashmap {"a" 1, "b" 2, "c" 3})
("a" string-hashmap)
; => ClassCastException java.lang.String cannot be cast to clojure.lang.IFn
(def keyword-hashmap {:a 1, :b 2, :c 3})
(:a keyword-hashmap)
; => 1
;; You can also pass a keyword a default value in case it's not found, just like get.
(:not-in-the-hashmap keyword-hashmap "not found!")
; => "not found!"
```
## Преобразование других коллекций в хэшмапы
Преобразование в hashmap является сложным. Чтобы продемонстрировать, давайте попробуем использовать его как `vec` или `seq` .
```
(hash-map [:a 1 :b 2 :c 3])
; => IllegalArgumentException No value supplied for key: [:a 1 :b 2 :c 3]
```
Функция `hash-map` считает, что мы пытаемся создать `hash-map` с `[:a 1 :b 2 :c 3]` качестве одного из ключей. Посмотрите, что произойдет, если мы дадим ему правильное количество аргументов:
```
(hash-map [:a 1 :b 2 :c 3] "foo")
; => {[:a 1 :b 2 :c 3] "foo"}
```
Чтобы преобразовать последовательность в хэш-карту, вам нужно будет использовать и понимать `apply` . К счастью, это довольно просто: `apply` существу деструкции коллекции перед тем, как применить к ней функцию.
```
;; These two expressions are exactly the same.
(+ 1 2 3)
; => 6
(apply + [1 2 3])
; => 6
```
Вот как вы преобразовали вектор в hashmap:
```
(apply hash-map [:a 1 :b 2 :c 3])
; => {:c 3, :b 2, :a 1}
;; This is the same as:
(hash-map :a 1 :b 2 :c 3)
; => {:c 3, :b 2, :a 1}
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/k9cOjo)
## Обновить хэш-карту
Вы можете обновить значения внутри HashMap с помощью `assoc` . Это позволяет добавлять новые пары ключ / значение или изменять старые.
```
(def outdated-hashmap {:a 1, :b 2, :c 3})
(def newer-hashmap (assoc outdated-hashmap :d 4))
newer-hashmap
; => {:a 1, :b 2, :c 3, :d 4}
(def newest-hashmap (assoc newer-hashmap :a 22))
newest-hashmap
; => {:a 22, :b 2, :c 3, :d 4}
;; Note that outdated-hashmap has not been mutated by any of this.
;; Assoc is pure and functional.
outdated-hashmap
; => {:a 1, :b 2, :c 3}
```
## Когда использовать хэш-карту?
Хешмап полезен, когда вы хотите дать имена вашим переменным. Если вы когда-нибудь думаете о себе: _«Что, если я использовал объект ...»,_ прежде чем вы выйдете из него и поймете, что используете Clojure, попробуйте использовать hashmap.
Они также полезны, если вы хотите связать два разных значения друг с другом. Возьмем, к примеру, шифр ROT13: вы можете связать `\A` с `\N` , `\B` с `\M` и т. Д. (Это было бы долго и скучно писать на большинстве языков, но у Clojure есть некоторые функции, которые могут сгенерировать его для вас и сделать это есело!_ )
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ": Point_left:") Предыдущая](//forum.freecodecamp.com/t/clojure-vectors/18421) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:") Главная ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:")](//forum.freecodecamp.com/t/clojure-resources/18422) | следующий ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ": Point_right:") |
| [Векторы](//forum.freecodecamp.com/t/clojure-vectors/18421) | [Содержание](//forum.freecodecamp.com/t/clojure-resources/18422) | Чтобы добавить |

View File

@@ -0,0 +1,93 @@
---
title: Clojure
localeTitle: Clojure
---
## Начало работы с Clojure
Прежде чем мы начнем, вы можете [установить Clojure](http://clojure.org/guides/getting_started) и [Leiningen](http://leiningen.org/#install) (который является инструментом для управления проектами в Clojure). Это позволит вам запустить Clojure в командной строке с помощью REPL (Read-Evaluate-Print-Loop).
## Определение переменных
Хлеб и масло любого языка программирования являются переменными и функциями. Определим переменную!
```
(def our-string "Hello world!")
```
Очень просто. Этот фрагмент кода использует макрос `def` чтобы связать строку ( `"Hello world!"` ) С символом ( `our-string` ). Мы также могли бы определить число, такое как `1` или `1.1` , символ, например `\a` или `\Z` , или нечто более сложное, как список или регулярное выражение ( _uuuugh_ ).
Обратите внимание, что наш код находится в круглых скобках, например, в списке, потому что все в Lisp - это список! (Это будет очень важно, когда мы начнем говорить о макросах.)
## Определение функций
Теперь давайте определим функцию!
```
(defn hello-world [] (println our-string))
```
Это немного сложнее. Как и `def` , он использует макрос ( `defn` ) для создания переменной - хотя на этот раз эта переменная является функцией. Пустой вектор (вектор - это тип списка - думайте об этом как массив) после того, как `hello-world` определяет аргументы этой функции - в этом случае у нас их нет. После этого код выполняет функцию. Он оценивает `our-string` , которая равна `"Hello world!"` , и печатает его на консоли. Давайте запустим его!
```
(hello-world)
; => Hello world!
; nil
```
Вы также можете написать следующее:
```
(def hello-world (fn [] (println our-string)))
```
`defn` - это просто ярлык, который поможет сохранить ваш код кратким. `(defn ...)` и `(def ... (fn ...))` одинаковы на практике.
## параметры
Ну, это было хорошо, но это было не очень интересно. Попробуем функцию с параметрами. Как насчет того, что добавляет 3 номера?
```
(defn add [xyz] (+ xyz))
(add 1 2 3)
; => 6
```
…Оставайтесь на линии. `(+ xyz)` ? Это выглядит смешно. Ну, Lisps написаны с использованием «префиксной нотации», что означает, что функция всегда на первом месте. Так как все математические операторы в Lisp ( `+ - * /` ) являются справедливыми функциями, они также выходят перед их аргументами (в данном случае `xyz` ).
Вы заметите, что у нашего вектора сейчас есть кое-что: `[xyz]` ! Всякий раз, когда функция имеет параметры, вы определяете их в этом векторе рядом с именем функции.
### деструктурирующие
Отличная характеристика аргументов в Clojure - разрушение. Это позволяет вам «вытаскивать» элементы из списка.
```
(defn add [[xy] z] (+ xyz))
(add [1 2] 3)
; => 6
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/SWlvKn)
Аргументами этой функции являются коллекция ( `[xy]` ) и число ( `z` ). Мы можем использовать деструктуризацию, чтобы вытащить первый и второй элементы из списка и называть их `x` и `y` .
### Функции с любым количеством параметров
Вы также можете определить функцию с произвольным числом аргументов, используя `&` .
```
(defn demonstrate-rest [first & rest]
(println first)
(println rest))
(demonstrate-rest 1 "foo" ["bar" 22])
; => 1
; ("foo" ["bar" 22])
; nil
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/VftymP)
Как вы можете видеть, используя `&` отделили аргументы нашей функции в одну переменную, называемую `first` и список переменных, называемых `rest` . Это означает, что наша функция может иметь любое количество аргументов!
## возврате
Возможно, вы заметили какие-то странные вещи. Всякий раз, когда мы используем `println` , кажется, что `nil` появляется в нашем выпуске. Кроме того, наша функция `add` возвращает `6` , но мы никогда не говорили ей возвращать что-либо.
В Clojure возвраты являются «неявными». Если вы использовали Ruby, вы, вероятно, знакомы с этой концепцией. Вместо того, чтобы сообщать нашей функции о возврате чего-либо, он оценивает весь код внутри своего тела и возвращает результат. Например, наша функция `add` оценивает `(+ xyz)` , а затем возвращает этот результат.
Причина, по которой наши функции, использующие вывод `println` `nil` заключается в том, что `println` оценивает значение `nil` . ( `nil` как `null` или `None` - ничего не представляет).
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ": Point_left:") Предыдущая](//forum.freecodecamp.com/t/what-is-clojure/18419) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:") Главная ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [следующий ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ": Point_right:")](//forum.freecodecamp.com/t/clojure-conditionals/18412) |
| [Резюме](//forum.freecodecamp.com/t/what-is-clojure/18419) | [Содержание](//forum.freecodecamp.com/t/clojure-resources/18422) | [Условные](//forum.freecodecamp.com/t/clojure-conditionals/18412) |

View File

@@ -0,0 +1,107 @@
---
title: Clojure Lists They Are Everything
localeTitle: Clojure Списки Они все
---
Списки являются фундаментальными для Clojure. Clojure - это Lisp, а Lisps были первоначально использованы для обработки списка. Все в Лиспе - это список!
```
(def foo "bar")
```
Этот кусок кода на самом деле является списком! Так что все между двумя круглыми скобками в Clojure. Интересно, не так ли? Это то, что делает Lisps настолько интересным - вы можете легко написать код, который генерирует новый код, потому что генерировать код так же просто, как составить список.
## Создание фактического списка
Проблема в том, что, поскольку все это список в Clojure, что-то вроде этого вернет ошибку:
```
(1 2 3 4 5)
; => ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn
```
Какое ужасное сообщение об ошибке. Что REPL пытается сказать нам, это: «1 не является функцией, и ее нельзя превратить в одну». Поскольку все в Lisp является списком, первый элемент любого списка рассматривается как функция, например `def` , `+` или `str` , поэтому, если мы пишем `(1 2 3 4 5)` , он обрабатывает первый элемент ( `1` ) как функции, которой это явно не является.
Мы можем решить это двумя способами. Один использует функцию `list` для построения списка, например, используя `str` для объединения строк вместе.
```
(list 1 2 3 4 5)
; => (1 2 3 4 5)
```
Вы также можете использовать цитирование. Цитирование списка в основном говорит компилятору, что этот список е_ является вызовом функции, и он не должен оценивать какой-либо из кода внутри него.
```
'(1 2 3 4 5)
; => (1 2 3 4 5)
```
Интересно, что вы также можете вызывать вызовы функций. Вот как работают макросы. Они довольно сложны и заслуживают собственной статьи, поэтому мы не будем здесь останавливаться.
```
;; Without a ' to quote it, this would return "foobarbaz".
'(str "foo" "bar" "baz")
; => (str "foo" "bar" "baz")
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/6c7UxY)
## Добавление в список
Списки предназначены для добавления, а не для добавления. Нет никакого реального способа добавления в список. Вы можете перейти к списку с помощью `cons` . `conj` также работает, но это предназначено для векторов, а `cons` быстрее для списков.
```
(cons 1 '(2 3 4))
; => (1 2 3 4)
```
## Извлечение из списков
Вы извлекаете элементы из списков с помощью `nth` . `get` не работает в списках, поскольку списки предназначены для последовательного доступа, а не для произвольного доступа. Обратите внимание, что `nth` работает с векторами, но медленнее, чем `get` из-за этого.
```
(nth '(1 2 3 4) 0)
; => 1
```
## Преобразование других коллекций в списки
Функция `list` не может преобразовать другие коллекции в списки, потому что она пытается построить список с использованием аргументов, которые ему даны. При пересылке `list` коллекция вернет список, содержащий эту коллекцию.
```
(list [1 2 3 4 5])
; => ([1 2 3 4 5])
```
Для преобразования в список используйте функцию `seq` .
```
(seq [1 2 3 4 5])
; => (1 2 3 4 5)
```
## Ленивые последовательности
Clojure имеет блестящую функцию, называемую «ленивые последовательности». Ленивая последовательность - это список, элементы которого не сгенерированы, пока вы не обратитесь к элементу последовательности позже, и в этот момент он оценивает все элементы последовательности до тех пор, пока вы не захотите. Это позволяет создавать «бесконечные» последовательности!
`range` - это, пожалуй, самая простая ленивая последовательность. Он содержит все числа.
```
(range 10)
; => (0 1 2 3 4 5 6 7 8 9)
(range -5 5)
; => (-5 -4 -3 -2 -1 0 1 2 3 4)
```
Вы можете использовать ленивые последовательности, чтобы делать действительно классные вещи, например, генерировать ленивую последовательность всех чисел фибоначчи.
```
(def fibs
(lazy-cat [0 1] (map + (rest fibs) fibs)))
(take 10 fibs) ;; this means, "evaluate the first 10 fibonacci numbers."
; => (0 1 1 2 3 5 8 13 21 34)
```
Этот пример немного продвинут, и вы не должны его понимать, если вы новичок. Это просто пример того, что вы можете сделать с ленивыми последовательностями. Возможно, вы все равно это поймете!
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/jwpvt8)
## Когда использовать список?
Использование вектора обычно предпочтительнее использования списка, так как нет никакого риска, что компилятор случайно оценивает вектор как функцию, и быстрее получить доступ к произвольным элементам вектора. Списки наиболее полезны в трех случаях:
* Создание кода с использованием макроса.
* Создание «бесконечных» ленивых последовательностей.
* Предоставление элементов коллекции.
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ": Point_left:") Предыдущая](//forum.freecodecamp.com/t/clojure-collections/18411) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:") Главная ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [следующий ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ": Point_right:")](//forum.freecodecamp.com/t/clojure-vectors/18421) |
| [Коллекции](//forum.freecodecamp.com/t/clojure-collections/18411) | [Содержание](//forum.freecodecamp.com/t/clojure-resources/18422) | [Векторы](//forum.freecodecamp.com/t/clojure-vectors/18421) |

View File

@@ -0,0 +1,97 @@
---
title: Clojure Looprecur
localeTitle: Clojure Looprecur
---
Возможно, вам придется понять, [`if`](//forum.freecodecamp.com/t/clojure-conditionals/18412) и [`let`](//forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415) полностью понять рекурсию в Clojure.
## `for` и `while`
Clojure не имеет циклов или циклов. Это имеет смысл, если вы думаете об этом. Цикл `for` изменяет переменную, и это не допускается в Clojure.
```
for (var i = 0; i < 10; i++) {
console.log(i);
}
```
`i++` означает, что мы добавляем его к переменной `i` каждый раз, когда цикл завершается - ясный пример изменяемой переменной.
`while` циклы менее явно зависят от изменения переменных, но они, как и для циклов.
```
var i = 0;
while (i < 10) {
console.log(i);
i++;
}
```
`while` циклов всегда есть условие, такое как `i < 10` , и будет ломаться, если это условие перестает быть истинным. Это означает, что у них должен быть какой-то побочный эффект (например, добавление 1 к `i` ), чтобы условие в конечном итоге было ложным; в противном случае цикл будет длиться вечно.
## Рекурсия
К счастью, у Clojure есть одна петля. Эти циклы используют рекурсию - функцию, которая вызывает себя. Простейшим рекурсивным алгоритмом является поиск положительного числа factorial (5 факториалов, например, `5 * 4 * 3 * 2` ).
```
(defn fact [x]
(loop [nx prod 1] ;; this works just like a 'let' binding.
(if (= 1 n) ;; this is the base case.
prod
(recur (dec n) (* prod n)))))
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/3iP3tI)
Вы заметите, что `(loop [nx prod 1] ...)` выглядит очень похоже на привязку `let` . Фактически это работает точно так же - здесь мы привязываем `n` к `x` и `prod` 1.
Каждая рекурсивная функция имеет «базовый регистр». Это условие, которое делает цикл остановки цикла. В этом случае наш цикл останавливается, если `n = 1` , и возвращает `prod` . Если `n` не равно 1, то цикл повторяется.
```
(recur (dec n) (* prod n))
```
Эта `recur` функция перезапускает цикл, но с разными привязками. На этот раз `n` не привязано к `x` , а привязано к `(dec n)` (что означает `decrement n` или `n - 1` ), а `prod` привязан к `(* prod n)` .
Поэтому, когда мы вызываем функцию, это происходит:
```
(fact 5)
; Loop 1: 5 != 1, so the loop recurs with 4 (5 - 1) and 5 (1 * 5).
; Loop 2: 4 != 1, so the loop recurs with 3 (4 - 1) and 20 (5 * 4).
; Loop 3: 3 != 1, so the loop recurs with 2 (3 - 1) and 60 (20 * 3).
; Loop 4: 2 != 1, so the loop recurs with 1 (2 - 1) and 120 (60 * 2).
; Loop 5: 1 == 1, so the function returns prod, which is now equal to 120.
; => 120
```
Гениальная вещь о рекурсии состоит в том, что сами переменные никогда не меняются. Единственное, что меняется, это то, о чем _говорят_ `n` и `prod` . Мы никогда не говорим, что `n--` , или `n += 2` .
## Зачем использовать loop / recur?
Вам может быть интересно, почему вы будете использовать `loop/recur` а не просто определять функцию, которая вызывает себя. Наша факториальная функция могла быть написана так:
```
(defn fact-no-loop [n]
(if (= 1 n)
1
(* n (fact-no-loop (dec n)))))
```
Это более красноречиво и работает аналогичным образом. Почему бы вы огда_ - _либо_ использовать цикл и повторялись?
### Оптимизация звонков
Если вы используете `loop/recur` , то компилятор (программное обеспечение, которое превращает Clojure-код в JTM-байт-код) знает, что вы хотите создать рекурсивный цикл. Это означает, что он пытается изо всех сил оптимизировать ваш код для рекурсии. Давайте сравним скорость `fact` и `fact-no-loop` :
```
(time (fact 20))
; => "Elapsed time: 0.083927 msecs"
; 2432902008176640000
(time (fact-no-loop 20))
; => "Elapsed time: 0.064937 msecs"
; 2432902008176640000
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/tpC0Xo)
В этом масштабе разница незначительна. Фактически, `fact-no-loop` иногда быстрее, чем `fact` из-за непредсказуемого характера компьютерной памяти. Однако в более широком масштабе такая оптимизация может сделать ваш код намного, намного быстрее.
### Реестр вложенности внутри функций
`fact-no-loop` работает без `loop/recur` потому что вся функция рекурсивна. Что, если мы хотим, чтобы часть нашей функции использовала рекурсивный цикл, а затем остальную часть, чтобы сделать что-то нерекурсивное? Нам нужно было бы определить две совершенно отдельные функции. Использование `loop/recur` позволяет использовать небольшую анонимную функцию.
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ": Point_left:") Предыдущая](//forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:") Главная ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:")](//forum.freecodecamp.com/t/clojure-resources/18422) | следующий ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ": Point_right:") |
| [Пусть привязки](//forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415) | [Содержание](//forum.freecodecamp.com/t/clojure-resources/18422) | Чтобы добавить |

View File

@@ -0,0 +1,79 @@
---
title: Clojure More on Functions
localeTitle: Clojure Больше о функциях
---
Функция! Они очень важны. Очень сложно делать что-либо без функции. Они являются неотъемлемой частью любого языка, но особенно Clojure, поскольку это функциональный язык программирования, который отвергает объектно-ориентированный дизайн. Давайте узнаем еще о них!
## Arity
**Arity** относится к числу аргументов, которые ожидает ваша функция.
```
;; add expects 2 arguments. Its arity is 2.
(defn add [xy] (+ xy))
(add 2 2)
; => 4
;; + itself is a function, and it can have any number of arguments.
(+ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16) ;; and so on...
; => 136
```
Clojure имеет специальный синтаксис, который позволяет вам делать свою функцию разными вещами в зависимости от количества аргументов, которые она получает. Это называется переменной arity.
```
(defn foo
([] ; if this function gets no arguments...
(println "Lisa needs braces!")) ; do this.
([arg1] ; if this function gets 1 argument...
(println "Dental plan!"))) ; do this instead!
(foo)
; => Lisa needs braces!
; nil
(foo "this is a placeholder argument.")
; => Dental plan!
; nil
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/sXGplb)
## Анонимные функции
Давайте посмотрим на очень простую функцию: функцию, которая добавляет 1 к числу.
```
;; I've called this function "my-inc" so you don't confuse it with inc.
;; inc is a built-in function that already does this for us.
(defn my-inc [n] (+ 1 n))
(inc' 5)
; => 6
```
Это выглядит довольно просто. Он принимает один параметр - `n` - и возвращает `n + 1` . Давайте ее разобьем.
```
(def my-inc-2 (fn [n] (+ 1 n)))
(inc' 5)
; => 6
```
Вы можете видеть из этого, что использование `defn` является просто сокращением для использования `(def ... (fn ...))` . Но это показывает что-то интересное. То, что мы на самом деле делаем, это не «определение функции», а просто привязка анонимной функции к специальному имени - `inc'` . Что, если мы не дадим ему имя?
```
((fn [n] (+ 1 n)) 5)
; => 6
```
Бам! Boom! Kapow! Анонимные функции. Теперь это может показаться бесполезным, но в конце концов это очень удобно для применения функций списков с использованием `map` , `reduce` и `filter` . Предоставление каждой функции, которую вы пишете, становится скучным и громоздким, быстрым.
Существует более короткий способ писать анонимные функции, предназначенные для очень коротких и простых функций. Это не позволяет деструктурировать или переменную arity. Однако это довольно кратким.
```
(#(+ 1 %) 5)
; => 6
```
`#(...)` - сокращенный способ определения анонимной функции. `%` относится к первому аргументу функции. Если ваша функция ожидает несколько аргументов, вы можете использовать `%1, %2, ... %n` .
```
(#(str %1 %2 %3) "foo" "bar" "baz")
; => "foobarbaz"
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/roYRgS)
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ": Point_left:") Предыдущая](//forum.freecodecamp.com/t/clojure-loop-recur/18418) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:") Главная ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [следующий ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ": Point_right:")](//forum.freecodecamp.com/t/clojure-collections/18411) |
| [Loop и Recur](//forum.freecodecamp.com/t/clojure-loop-recur/18418) | [Содержание](//forum.freecodecamp.com/t/clojure-resources/18422) | [Коллекции](/http://forum.freecodecamp.com/t/clojure-collections/18411) |

View File

@@ -0,0 +1,19 @@
---
title: Clojure Resources
localeTitle: Ресурсы Clojure
---
![Логотип Clojure](//discourse-user-assets.s3.amazonaws.com/original/2X/3/3f3afa51f5d2c790faed68bfdd695d9f280e4480.png)
[Clojure](https://clojure.org/) - это диалект Lisp с акцентом на функциональное программирование. Он был выпущен в 2007 году Ричем Хики и с тех пор приобрел большую популярность среди веб-разработчиков.
Чтобы узнать о некоторых основных функциях языка, вы можете ознакомиться с [документацией](https://clojuredocs.org/) .
Вы также можете обратиться к любой из этих статей:
* [Резюме - Зачем использовать Clojure?](http://forum.freecodecamp.com/t/what-is-clojure/18419)
* [Основы - определение некоторых переменных и функций](http://forum.freecodecamp.com/t/clojure-the-basics/18410)
* [Условные обозначения - использование логики для добавления сложного потока управления к вашим программам](http://forum.freecodecamp.com/t/clojure-conditionals/18412)
* [Пусть привязки - использование локальных переменных](http://forum.freecodecamp.com/t/clojure-create-local-variables-with-let/18415)
* [Loop и Recur - использование рекурсии для создания циклов в Clojure](http://forum.freecodecamp.com/t/clojure-loop-recur/18418)
Для краткого и простого обучения можно использовать бесплатную онлайн-книгу [Clojure for the Brave and True](https://www.braveclojure.com/foreword/) .

View File

@@ -0,0 +1,93 @@
---
title: Clojure the Basics
localeTitle: Clojure основы
---
### Начиная
Прежде чем мы начнем, вы можете [установить Clojure](http://clojure.org/guides/getting_started) и [Leiningen](http://leiningen.org/#install) (который является инструментом для управления проектами в Clojure). Это позволит вам запустить Clojure в командной строке с помощью REPL (Read-Evaluate-Print-Loop).
## Определение переменных
Хлеб и масло любого языка программирования являются переменными и функциями. Определим переменную!
```
(def our-string "Hello world!")
```
Очень просто. Этот фрагмент кода использует макрос `def` чтобы связать строку ( `"Hello world!"` ) С символом ( `our-string` ). Мы также могли бы определить число, такое как `1` или `1.1` , символ, например `\a` или `\Z` , или нечто более сложное, как список или регулярное выражение ( _uuuugh_ ).
Обратите внимание, что наш код находится в круглых скобках, например, в списке, потому что все в Lisp - это список! (Это будет очень важно, когда мы начнем говорить о макросах.)
## Определение функций
Теперь давайте определим функцию!
```
(defn hello-world [] (println our-string))
```
Это немного сложнее. Как и `def` , он использует макрос ( `defn` ) для создания переменной - хотя на этот раз эта переменная является функцией. Пустой вектор (вектор - это тип списка - думайте об этом как массив) после того, как `hello-world` определяет аргументы этой функции - в этом случае у нас их нет. После этого код выполняет функцию. Он оценивает `our-string` , которая равна `"Hello world!"` , и печатает его на консоли. Давайте запустим его!
```
(hello-world)
; => Hello world!
; nil
```
Вы также можете написать следующее:
```
(def hello-world (fn [] (println our-string)))
```
`defn` - это просто ярлык, который поможет сохранить ваш код кратким. `(defn ...)` и `(def ... (fn ...))` одинаковы на практике.
## параметры
Ну, это было хорошо, но это было не очень интересно. Попробуем функцию с параметрами. Как насчет того, что добавляет 3 номера?
```
(defn add [xyz] (+ xyz))
(add 1 2 3)
; => 6
```
…Оставайтесь на линии. `(+ xyz)` ? Это выглядит смешно. Ну, Lisps написаны с использованием «префиксной нотации», что означает, что функция всегда на первом месте. Так как все математические операторы в Lisp ( `+ - * /` ) являются справедливыми функциями, они также выходят перед их аргументами (в данном случае `xyz` ).
Вы заметите, что у нашего вектора сейчас есть кое-что: `[xyz]` ! Всякий раз, когда функция имеет параметры, вы определяете их в этом векторе рядом с именем функции.
### деструктурирующие
Отличная характеристика аргументов в Clojure - разрушение. Это позволяет вам «вытаскивать» элементы из списка.
```
(defn add [[xy] z] (+ xyz))
(add [1 2] 3)
; => 6
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/SWlvKn)
Аргументами этой функции являются коллекция ( `[xy]` ) и число ( `z` ). Мы можем использовать деструктуризацию, чтобы вытащить первый и второй элементы из списка и называть их `x` и `y` .
### Функции с любым количеством параметров
Вы также можете определить функцию с произвольным числом аргументов, используя `&` .
```
(defn demonstrate-rest [first & rest]
(println first)
(println rest))
(demonstrate-rest 1 "foo" ["bar" 22])
; => 1
; ("foo" ["bar" 22])
; nil
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/VftymP)
Как вы можете видеть, используя `&` отделили аргументы нашей функции в одну переменную, называемую `first` и список переменных, называемых `rest` . Это означает, что наша функция может иметь любое количество аргументов!
## возврате
Возможно, вы заметили какие-то странные вещи. Всякий раз, когда мы используем `println` , кажется, что `nil` появляется в нашем выпуске. Кроме того, наша функция `add` возвращает `6` , но мы никогда не говорили ей возвращать что-либо.
В Clojure возвраты являются «неявными». Если вы использовали Ruby, вы, вероятно, знакомы с этой концепцией. Вместо того, чтобы сообщать нашей функции о возврате чего-либо, он оценивает весь код внутри своего тела и возвращает результат. Например, наша функция `add` оценивает `(+ xyz)` , а затем возвращает этот результат.
Причина, по которой наши функции, использующие вывод `println` `nil` заключается в том, что `println` оценивает значение `nil` . ( `nil` как `null` или `None` - ничего не представляет).
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ": Point_left:") Предыдущая](//forum.freecodecamp.com/t/what-is-clojure/18419) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:") Главная ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [следующий ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ": Point_right:")](//forum.freecodecamp.com/t/clojure-conditionals/18412) |
| [Резюме](//forum.freecodecamp.com/t/what-is-clojure/18419) | [Содержание](//forum.freecodecamp.com/t/clojure-resources/18422) | [Условные](//forum.freecodecamp.com/t/clojure-conditionals/18412) |

View File

@@ -0,0 +1,71 @@
---
title: Clojure Vectors
localeTitle: Clojure Vectors
---
Вектор, пожалуй, самый простой тип коллекции в Clojure. Вы можете думать об этом как о массиве в Javascript. Определим простой вектор:
```
(def a-vector [1 2 3 4 5])
;; Alternatively, use the vector function:
(def another-vector (vector 1 2 3 4 5))
;; You can use commas to separate items, since Clojure treats them as whitespace.
(def comma-vector [1, 2, 3, 4, 5])
```
Вы увидите, что он использует квадратные скобки, как и массив в JS. Так как Clojure, как JS, динамически типизируется, векторы могут содержать элементы любого типа, включая другие векторы.
```
(def mixed-type-vector [1 "foo" :bar ["spam" 22] #"^baz$"])
```
## Добавление элементов в вектор
Вы можете добавлять элементы к вектору, используя `conj` . Вы также можете добавить к списку, используя `into` , но обратите внимание, что `into` предназначен для слияния двух векторов, поэтому оба его аргумента должны быть векторами, а использование `into` них медленнее, чем использование `conj` .
```
(time (conj [1 2] 3))
; => "Elapsed time: 0.032206 msecs"
; [1 2 3]
(time (into [1] [2 3]))
; => "Elapsed time: 0.078499 msecs"
; [1 2 3]
```
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [IDEOne!](https://ideone.com/wBSUEd)
## Получение элементов из вектора
Вы можете извлекать элементы из вектора с помощью `get` . Это эквивалентно использованию записи в виде скобок для доступа к элементам в массиве на многих императивных языках. Элементы в векторе 0-индексируются, считая слева.
```
var arr = [1, 2, 3, 4, 5];
arr[0];
// => 1
```
В Clojure это будет написано так:
```
(def a-vector [1 2 3 4 5])
(get a-vector 0)
; => 1
```
Вы также можете `get` значение по умолчанию, если вы укажете ему индекс, который не находится в массиве.
```
;; the list doesn't have 2147483647 elements, so it'll return a string instead.
(get a-vector 2147483646 "sorry, not found!")
; => "sorry, not found!"
```
## Преобразование других коллекций в векторы
Невекторные структуры данных могут быть преобразованы в векторы с использованием функции `vec` . С hashmaps это создает 2D-вектор, содержащий пары ключей и значений.
```
(vec '(1 2 3 4 5))
; => [1 2 3 4 5]
(vec {:jack "black" :barry "white"})
; => [[:jack "black"] [:barry "white"]]
```
## Когда использовать вектор?
Вектор должен использоваться почти во всех случаях, если вам нужна коллекция, потому что у них кратчайшее время произвольного доступа, что позволяет легко извлекать элементы из вектора. Обратите внимание, что векторы упорядочены. Если заказ не имеет значения, лучше использовать набор. Также обратите внимание, что векторы предназначены для добавления элементов; если вам нужно добавить элементы, вы можете использовать список.
| [![:point_left:](//forum.freecodecamp.com/images/emoji/emoji_one/point_left.png?v=2 ": Point_left:") Предыдущая](//forum.freecodecamp.com/t/clojure-lists-they-are-everything/18417) | [![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:") Главная ![:book:](//forum.freecodecamp.com/images/emoji/emoji_one/book.png?v=2 ":книга:")](//forum.freecodecamp.com/t/clojure-resources/18422) | [следующий ![:point_right:](//forum.freecodecamp.com/images/emoji/emoji_one/point_right.png?v=2 ": Point_right:")](//forum.freecodecamp.com/t/clojure-hashmaps/18414) |
| [Списки](//forum.freecodecamp.com/t/clojure-lists-they-are-everything/18417) | [Содержание](//forum.freecodecamp.com/t/clojure-resources/18422) | [Hashmaps](//forum.freecodecamp.com/t/clojure-hashmaps/18414) |