freeCodeCamp/guide/russian/clojure/lists-are-everything/index.md

107 lines
8.2 KiB
Markdown
Raw Normal View History

2018-10-12 20:00:59 +00:00
---
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) |