Merge ec99e1227c into faa02b5fae
This commit is contained in:
commit
71758031a8
12 changed files with 194 additions and 204 deletions
154
README.md
154
README.md
|
|
@ -1,48 +1,43 @@
|
|||
# Clojure Koans
|
||||
|
||||
The Clojure Koans are a fun way to get started with Clojure - no experience
|
||||
assumed or required. Follow the instructions below to start making tests pass!
|
||||
Для того чтобы приступить к решению Clojure коанов, следуйте инструкциям ниже.
|
||||
|
||||
|
||||
## Getting Started
|
||||
## Установка
|
||||
|
||||
I recommend starting from a cloned or forked repo. This way you'll be able to
|
||||
track your progress in Git. You might want to create your own branch - that way
|
||||
if you pull back the latest koans from master, it'll be a bit easier to manage
|
||||
the inevitable conflicts if we make changes to exercises you've already
|
||||
completed.
|
||||
Прежде всего клонируйте репозиторий или создайте свой форк. Далее вы можете создать отдельную ветку
|
||||
чтобы избежать конфликтов при обновлении коанов.
|
||||
|
||||
You have a few options for installation:
|
||||
Способы установки зависимостей:
|
||||
|
||||
- Install the dependencies for the koans (such as Clojure) on your machine
|
||||
- Use Vagrant and the configuration in this repository
|
||||
- Use Docker
|
||||
- Установите все зависимости локально
|
||||
- Используйте Vagrant
|
||||
- Используйте Docker
|
||||
|
||||
Instructions for each option are below!
|
||||
Инструкции для каждого для реализации каждого способа ниже.
|
||||
|
||||
|
||||
### Installation on Your Machine
|
||||
### Локальная установка
|
||||
|
||||
The only things you'll need to run the Clojure Koans are:
|
||||
Вам необходимо:
|
||||
|
||||
- JDK (I suggest version 8, but anything 6 or above should work fine)
|
||||
- [Leiningen](http://github.com/technomancy/leiningen), a build tool for Clojure
|
||||
- JDK (от 6 до 8 версии)
|
||||
- [Leiningen](http://github.com/technomancy/leiningen), инструмент сборки для Clojure
|
||||
|
||||
Once you've cloned this repo and installed the dependencies, you can run:
|
||||
После этого выполните в клонированной папке:
|
||||
|
||||
```
|
||||
lein repl
|
||||
```
|
||||
|
||||
to make sure all the dependencies get downloaded properly (and then `(exit)`
|
||||
when you want to quit). See below for details on the REPL.
|
||||
Leiningen скачает все зависимости, затем наберите `(exit)` чтобы выйти.
|
||||
|
||||
|
||||
### Installation with Vagrant
|
||||
### Установка, используя Vagrant
|
||||
|
||||
Make sure you have [Vagrant](https://www.vagrantup.com/) and
|
||||
[VirtualBox](https://www.virtualbox.org) installed.
|
||||
In the root directory of the project, execute:
|
||||
Установите [Vagrant](https://www.vagrantup.com/) и
|
||||
[VirtualBox](https://www.virtualbox.org).
|
||||
В корневой директории выполните:
|
||||
|
||||
```
|
||||
vagrant up
|
||||
|
|
@ -52,39 +47,38 @@ lein koan run
|
|||
```
|
||||
|
||||
|
||||
### Installation with Docker
|
||||
### Установка, используя Docker
|
||||
|
||||
Once you've got [Docker](https://www.docker.com/) installed, you're basically
|
||||
all set. You can run these commands to get started:
|
||||
Установите [Docker](https://www.docker.com/), затем выполните:
|
||||
|
||||
To run koans:
|
||||
для запуска коанов:
|
||||
|
||||
```
|
||||
docker run --rm -it -v $(pwd):/app -w /app clojure lein koan run
|
||||
```
|
||||
|
||||
To start up a REPL:
|
||||
для запуска REPL:
|
||||
|
||||
```
|
||||
docker run --rm -it -v $(pwd):/app -w /app clojure lein repl
|
||||
```
|
||||
|
||||
|
||||
## Running the Koans
|
||||
## Запуск коанов
|
||||
|
||||
Run the koans via:
|
||||
Команда:
|
||||
|
||||
`lein koan run`
|
||||
|
||||
If want to run directly from a REPL, once you are inside the `lein repl` prompt you can run the koans with
|
||||
Для запуска из REPL:
|
||||
|
||||
`(exec "run")`
|
||||
|
||||
Either way, it's an auto-runner, so as you save your files with the correct
|
||||
answers, it will advance you to the next koan or file (conveniently, all files
|
||||
are prefixed with the sequence that you should follow).
|
||||
В любом случае программа запустится и будет ожидать сохранения файла с коанами
|
||||
и даст вам знать правильно ли было решение или нет.
|
||||
Каждый коан сопровождён указаниями и направляющими вопросами.
|
||||
|
||||
You'll see something like this:
|
||||
Пример:
|
||||
|
||||
Now meditate on /home/colin/Projects/clojure-koans/src/koans/01_equalities.clj:3
|
||||
---------------------
|
||||
|
|
@ -92,36 +86,33 @@ You'll see something like this:
|
|||
We shall contemplate truth by testing reality, via equality.
|
||||
(= __ true)
|
||||
|
||||
The output is telling you that you have a failing test in the file named
|
||||
`01_equalities.clj`, on line 3. So you need to open that file up and make
|
||||
it pass! You'll always be filling in the blanks to make tests pass.
|
||||
Sometimes there could be several correct answers (or even an infinite number):
|
||||
any of them will work in these cases. Some tests will pass even if you replace
|
||||
the blanks with whitespace (or nothing) instead of the expected answer. Make sure
|
||||
you give one correct expression to replace each blank.
|
||||
Программа сообщает вам о том, что в файле `01_equalities.clj`, строка 3 тест не пройден
|
||||
и коан не решён. Подумайте и внесите изменения!
|
||||
Вам всегда будет предложено заполнить пустое место, обозначенное символами подчёркивания.
|
||||
Иногда способов решения несколько, некоторые тесты успешно пройдут даже при замене символов подчёркивания
|
||||
на пробел.
|
||||
|
||||
The koans differ from normal TDD in that the tests are already written for you,
|
||||
so you'll have to pay close attention to the failure messages, because up until
|
||||
the very end, making a test pass means that the next failure message comes
|
||||
up.
|
||||
Коаны отличаются от TDD, т.к. тесты уже написаны за вас.
|
||||
Следите за сообщениями о непройденном тесте — они будут появляться вплоть до решения всех коанов.
|
||||
Соответственно при прохождении одного коана, вы увидите собщение об ошибке при прохождении следующего,
|
||||
ещё не решённого вами коана. Вы решаете следующий и так далее, пока не решите последний.
|
||||
|
||||
While it might be easy (especially at first) to fill in the blanks making
|
||||
things pass, you should work thoughtfully, making sure you understand why the
|
||||
answer is what it is. Enjoy your path to Clojure enlightenment!
|
||||
Постарайтесь обдумывать ваше решение и вполне понимать почему правильный ответ именно таков.
|
||||
Наслаждайтесь вашим путём к Clojure-просветлению!
|
||||
|
||||
|
||||
## Trying more things out
|
||||
## Используйте REPL
|
||||
|
||||
It's very useful to try things out in a REPL (Read-Evaluate-Print Loop)
|
||||
whenever you get stuck or curious. Run:
|
||||
Помимо коанов, практикуйтесь и читайте документацию используя интерактивную командную строку:
|
||||
|
||||
```
|
||||
lein repl
|
||||
```
|
||||
|
||||
and you'll be able to type expressions in, and see what output they produce.
|
||||
Вводите выражения и программа будет сразу выводить результат — это очень удобно и
|
||||
ускоряет изучение языка.
|
||||
|
||||
Here are some interesting commands you might try, once you're in a running REPL:
|
||||
Попробуйте ввести эти команды:
|
||||
|
||||
```clojure
|
||||
(find-doc "vec")
|
||||
|
|
@ -129,55 +120,54 @@ Here are some interesting commands you might try, once you're in a running REPL:
|
|||
(doc vec)
|
||||
```
|
||||
|
||||
And if those still don't make sense:
|
||||
И эти:
|
||||
|
||||
```clojure
|
||||
(doc doc)
|
||||
(doc find-doc)
|
||||
```
|
||||
|
||||
will show you what those commands mean.
|
||||
|
||||
You can exit the REPL with `CTRL-d`, `(exit)`, or `(quit)`.
|
||||
Для окончания работы с REPL используйте `CTRL-d`, `(exit)`, или `(quit)`.
|
||||
|
||||
|
||||
## Contributing
|
||||
## Развитие
|
||||
|
||||
Patches are encouraged! Make sure the answer sheet still passes
|
||||
(`lein koan test`), and send a pull request.
|
||||
Убедитесь, что (`lein koan test`) пройдены и присылайте патчи в pull request.
|
||||
|
||||
The file ideaboard.txt has lots of good ideas for new koans to start, or things
|
||||
to add to existing koans. So write some fun exercises, add your answers to
|
||||
`resources/koans.clj`, and we'll get them in there!
|
||||
Файл ideaboard.txt содержит различные идеи для реализации новых или изменения текущих коанов.
|
||||
Ответы на упражнения пишите в `resources/koans.clj`!
|
||||
|
||||
Please follow the guidelines in
|
||||
http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html for
|
||||
commmit messages, and put your code in a feature branch (not master) before
|
||||
making the pull request. This makes patches easier to review.
|
||||
Следуйте эти рекомендациям
|
||||
http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html.
|
||||
Для упрощения оценки ваших патчей, — сохраняйте код в feature ветку (не master) перед pull request.
|
||||
|
||||
Feel free to contact me (Colin Jones / trptcolin) on Github or elsewhere if you
|
||||
have any questions or want more direction before you start pitching in.
|
||||
Если у вас остались вопросы или нужны рекомендации,
|
||||
связывайтесь со мной (Colin Jones / trptcolin) через Github или иным способом.
|
||||
|
||||
|
||||
## Contributors
|
||||
## Участники
|
||||
|
||||
https://github.com/functional-koans/clojure-koans/contributors
|
||||
|
||||
|
||||
## Credits
|
||||
### Перевод на русский язык
|
||||
|
||||
These exercises were started by [Aaron Bedra](http://github.com/abedra) of
|
||||
[Relevance, Inc.](http://github.com/relevance) in early 2010, as a learning
|
||||
tool for newcomers to functional programming. Aaron's macro-fu makes these
|
||||
koans clear and fun to use and improve upon, and without Relevance's
|
||||
initiative, this project would not exist.
|
||||
[Alex Gorelov](https://github.com/brannx)
|
||||
|
||||
Using the [koans](http://en.wikipedia.org/wiki/koan) metaphor as a tool for
|
||||
learning a programming language started with the
|
||||
[Ruby Koans](http://rubykoans.com) by [EdgeCase](http://github.com/edgecase).
|
||||
## Благодарность
|
||||
|
||||
Эти упражнения создавались [Aaron Bedra](http://github.com/abedra)
|
||||
[Relevance, Inc.](http://github.com/relevance) в начале 2010 как инструмент
|
||||
для изучения функционального программирования для новичков.
|
||||
Макрос-фу Аарона делали эти коаны доступными для использования и изучения языка,
|
||||
а также для их дальнейшей разработки и улучшения.
|
||||
Без инициативы со стороны Relevance Inc. этот проект не был бы осуществлён.
|
||||
|
||||
Использование впервые [коанов](http://en.wikipedia.org/wiki/koan) в качестве метафоры
|
||||
для обучающих упражнений было заслугой [Ruby Koans](http://rubykoans.com) от [EdgeCase](http://github.com/edgecase).
|
||||
|
||||
|
||||
## License
|
||||
## Лицензия
|
||||
|
||||
The use and distribution terms for this software are covered by the
|
||||
Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
|
|
|
|||
|
|
@ -2,38 +2,38 @@
|
|||
(:require [koan-engine.core :refer :all]))
|
||||
|
||||
(meditations
|
||||
"We shall contemplate truth by testing reality, via equality"
|
||||
"Критерием истины является тест на равенство"
|
||||
(= __ true)
|
||||
|
||||
"To understand reality, we must compare our expectations against reality"
|
||||
"Проверять истинность нужно сравнением исходного с предположением"
|
||||
(= __ (+ 1 1))
|
||||
|
||||
"You can test equality of many things"
|
||||
"Тестировать на равенство можно многое"
|
||||
(= (+ 3 4) 7 (+ 2 __))
|
||||
|
||||
"Some things may appear different, but be the same"
|
||||
"Что-то может показаться отличным, но оставаться равным"
|
||||
(= __ (= 2 2/1))
|
||||
|
||||
"You cannot generally float to heavens of integers"
|
||||
"Целое не равно дробному"
|
||||
(= __ (= 2 2.0))
|
||||
|
||||
"But a looser equality is also possible"
|
||||
"Хотя может быть равнозначно"
|
||||
(= __ (== 2.0 2))
|
||||
|
||||
"Something is not equal to nothing"
|
||||
"Ничто не равно чему-либо"
|
||||
(= __ (not (= 1 nil)))
|
||||
|
||||
"Strings, and keywords, and symbols: oh my!"
|
||||
"Строки, ключи, символы!!!"
|
||||
(= __ (= "hello" :hello 'hello))
|
||||
|
||||
"Make a keyword with your keyboard"
|
||||
"Создавайте ключевые слова используя обычные"
|
||||
(= :hello (keyword __))
|
||||
|
||||
"Symbolism is all around us"
|
||||
"Кругом символизм"
|
||||
(= 'hello (symbol __))
|
||||
|
||||
"What could be equivalent to nothing?"
|
||||
"Так чему же равно ничто?"
|
||||
(= __ nil)
|
||||
|
||||
"When things cannot be equal, they must be different"
|
||||
"Разное не равно"
|
||||
(not= :fill-in-the-blank __))
|
||||
|
|
|
|||
|
|
@ -3,68 +3,68 @@
|
|||
[clojure.string :as string]))
|
||||
|
||||
(meditations
|
||||
"A string is nothing more than text surrounded by double quotes"
|
||||
"Строка — это текст, обрамлённый двойными кавычками"
|
||||
(= __ "hello")
|
||||
|
||||
"But double quotes are just magic on top of something deeper"
|
||||
"Но это лишь вершина айсберга"
|
||||
(= __ (str 'world))
|
||||
|
||||
"You can do more than create strings, you can put them together"
|
||||
"Создавая одну строку можно объединением нескольких"
|
||||
(= "Cool right?" (str __ __))
|
||||
|
||||
"You can even get certain characters"
|
||||
"Можно получить символьный литерал"
|
||||
(= \C (get "Characters" __))
|
||||
|
||||
"Or even count the characters"
|
||||
"Сосчитать сколько их"
|
||||
(= __ (count "Hello World"))
|
||||
|
||||
"But strings and characters are not the same"
|
||||
"Но он — не строка"
|
||||
(= __ (= \c "c"))
|
||||
|
||||
"What if you only wanted to get part of a string?"
|
||||
"А что если нужна лишь часть строки?"
|
||||
(= "World" (subs "Hello World" __ __))
|
||||
|
||||
"How about joining together elements in a list?"
|
||||
"Объединяем элементы в строку"
|
||||
(= __ (string/join '(1 2 3)))
|
||||
|
||||
"What if you wanted to separate them out?"
|
||||
"Объединяем, но разделяя между собой"
|
||||
(= "1, 2, 3" (string/join __ '(1 2 3)))
|
||||
|
||||
"Maybe you want to separate out all your lines"
|
||||
"Можно разделить построчно"
|
||||
(= [__ __ __] (string/split-lines "1\n2\n3"))
|
||||
|
||||
"You may want to make sure your words are backwards"
|
||||
"Можно инвертировать"
|
||||
(= __ (string/reverse "hello"))
|
||||
|
||||
"Maybe you want to find the index of the first occurrence of a substring"
|
||||
"Можно найти индекс первого совпадения"
|
||||
(= 0 (string/index-of "hello world" __))
|
||||
|
||||
"Or maybe the last index of the same"
|
||||
"Или последнего"
|
||||
(= __ (string/last-index-of "hello world, hello" "hello"))
|
||||
|
||||
"But when something doesn't exist, nothing is found"
|
||||
"А если ничто не совпало, то что мы получим?"
|
||||
(= __ (string/index-of "hello world" "bob"))
|
||||
|
||||
"Sometimes you don't want whitespace cluttering the front and back"
|
||||
"Иногда неплохо бы избавиться от пробелов"
|
||||
(= __ (string/trim " \nhello world \t \n"))
|
||||
|
||||
"You can check if something is a char"
|
||||
"Тест на символьный литерал"
|
||||
(= __ (char? \c))
|
||||
|
||||
"But it may not be"
|
||||
"Тут точно не пройдёт"
|
||||
(= __ (char? "a"))
|
||||
|
||||
"But chars aren't strings"
|
||||
"«Чары» — они не строки"
|
||||
(= __ (string? \b))
|
||||
|
||||
"Strings are strings"
|
||||
"А строки — строки"
|
||||
(= true (string? __))
|
||||
|
||||
"Some strings may be blank"
|
||||
"Иногда и пустые"
|
||||
(= __ (string/blank? ""))
|
||||
|
||||
"Even if at first glance they aren't"
|
||||
"Хотя на первый взгляд и не скажешь"
|
||||
(= __ (string/blank? " \n \t "))
|
||||
|
||||
"However, most strings aren't blank"
|
||||
"Всё же большинство строк не пусты"
|
||||
(= __ (string/blank? "hello?\nare you out there?")))
|
||||
|
|
|
|||
|
|
@ -2,43 +2,43 @@
|
|||
(:require [koan-engine.core :refer :all]))
|
||||
|
||||
(meditations
|
||||
"Lists can be expressed by function or a quoted form"
|
||||
"Списки создаются фукцией или кавычкой"
|
||||
(= '(__ __ __ __ __) (list 1 2 3 4 5))
|
||||
|
||||
"They are Clojure seqs (sequences), so they allow access to the first"
|
||||
"Они являются Clojure seqs (последовательностями); можно получить первый элемент"
|
||||
(= __ (first '(1 2 3 4 5)))
|
||||
|
||||
"As well as the rest"
|
||||
"И остальные, кроме первого"
|
||||
(= __ (rest '(1 2 3 4 5)))
|
||||
|
||||
"Count your blessings"
|
||||
"Сосчитай словечки"
|
||||
(= __ (count '(dracula dooku chocula)))
|
||||
|
||||
"Before they are gone"
|
||||
"Ну, если они есть…"
|
||||
(= __ (count '()))
|
||||
|
||||
"The rest, when nothing is left, is empty"
|
||||
"Когда ничего кроме списка не осталось, что получаем?"
|
||||
(= __ (rest '(100)))
|
||||
|
||||
"Construction by adding an element to the front is easy"
|
||||
"Создаём новый список добавляя элемент в начало списка"
|
||||
(= __ (cons :a '(:b :c :d :e)))
|
||||
|
||||
"Conjoining an element to a list isn't hard either"
|
||||
"Соединяем список и элемент — получаем новый список"
|
||||
(= __ (conj '(:a :b :c :d) :e))
|
||||
|
||||
"You can use a list like a stack to get the first element"
|
||||
"Список — он как стек, берём с вершины"
|
||||
(= __ (peek '(:a :b :c :d :e)))
|
||||
|
||||
"Or the others"
|
||||
"Или всё остальное"
|
||||
(= __ (pop '(:a :b :c :d :e)))
|
||||
|
||||
"But watch out if you try to pop nothing"
|
||||
"А когда остального то и нет! Исключение!"
|
||||
(= __ (try
|
||||
(pop '())
|
||||
(catch IllegalStateException e
|
||||
"No dice!")))
|
||||
|
||||
"The rest of nothing isn't so strict"
|
||||
"Но не для этой функции. Раз элементов нет, вернёт хоть список"
|
||||
(= __ (try
|
||||
(rest '())
|
||||
(catch IllegalStateException e
|
||||
|
|
|
|||
|
|
@ -2,32 +2,32 @@
|
|||
(:require [koan-engine.core :refer :all]))
|
||||
|
||||
(meditations
|
||||
"You can use vectors in clojure as array-like structures"
|
||||
"Векторы в Clojure похожи на массивы"
|
||||
(= __ (count [42]))
|
||||
|
||||
"You can create a vector from a list"
|
||||
"Можно их содать из списка"
|
||||
(= __ (vec '(1)))
|
||||
|
||||
"Or from some elements"
|
||||
"Или из ничего"
|
||||
(= __ (vector nil nil))
|
||||
|
||||
"But you can populate it with any number of elements at once"
|
||||
"Число элементов — ваше дело"
|
||||
(= [1 __] (vec '(1 2)))
|
||||
|
||||
"Conjoining to a vector is different than to a list"
|
||||
"Добавляем элемент, помним что вектор «похож» на массив"
|
||||
(= __ (conj [111 222] 333))
|
||||
|
||||
"You can get the first element of a vector like so"
|
||||
"Получаем первый элемент"
|
||||
(= __ (first [:peanut :butter :and :jelly]))
|
||||
|
||||
"And the last in a similar fashion"
|
||||
"Последний элемент"
|
||||
(= __ (last [:peanut :butter :and :jelly]))
|
||||
|
||||
"Or any index if you wish"
|
||||
"Да какой угодно элемент"
|
||||
(= __ (nth [:peanut :butter :and :jelly] 3))
|
||||
|
||||
"You can also slice a vector"
|
||||
"Нарезаем вектор"
|
||||
(= __ (subvec [:peanut :butter :and :jelly] 1 3))
|
||||
|
||||
"Equality with collections is in terms of values"
|
||||
"Коллекции сравниваются по их элементам"
|
||||
(= (list 1 2 3) (vector 1 2 __)))
|
||||
|
|
|
|||
|
|
@ -3,20 +3,20 @@
|
|||
[clojure.set :as set]))
|
||||
|
||||
(meditations
|
||||
"You can create a set by converting another collection"
|
||||
"Создаём множество из другой коллекции"
|
||||
(= #{3} (set __))
|
||||
|
||||
"Counting them is like counting other collections"
|
||||
"Считаем как обычно"
|
||||
(= __ (count #{1 2 3}))
|
||||
|
||||
"Remember that a set is a *mathematical* set"
|
||||
"Множество — оно математическое"
|
||||
(= __ (set '(1 1 2 2 3 3 4 4 5 5)))
|
||||
|
||||
"You can ask clojure for the union of two sets"
|
||||
"Объединение"
|
||||
(= __ (set/union #{1 2 3 4} #{2 3 5}))
|
||||
|
||||
"And also the intersection"
|
||||
"Пересечение"
|
||||
(= __ (set/intersection #{1 2 3 4} #{2 3 5}))
|
||||
|
||||
"But don't forget about the difference"
|
||||
"Разность"
|
||||
(= __ (set/difference #{1 2 3 4 5} #{2 3 5})))
|
||||
|
|
|
|||
|
|
@ -2,60 +2,60 @@
|
|||
(:require [koan-engine.core :refer :all]))
|
||||
|
||||
(meditations
|
||||
"Don't get lost when creating a map"
|
||||
"Не потеряйтесь при создании хэш-карты"
|
||||
(= {:a 1 :b 2} (hash-map :a 1 __ __))
|
||||
|
||||
"A value must be supplied for each key"
|
||||
"Каждому ключу — значение"
|
||||
(= {:a 1} (hash-map :a __))
|
||||
|
||||
"The size is the number of entries"
|
||||
"Размер определяется числом пар"
|
||||
(= __ (count {:a 1 :b 2}))
|
||||
|
||||
"You can look up the value for a given key"
|
||||
"Узнать значение можно по ключу"
|
||||
(= __ (get {:a 1 :b 2} :b))
|
||||
|
||||
"Maps can be used as functions to do lookups"
|
||||
"Прямо как функции"
|
||||
(= __ ({:a 1 :b 2} :a))
|
||||
|
||||
"And so can keywords"
|
||||
"И ключи тоже"
|
||||
(= __ (:a {:a 1 :b 2}))
|
||||
|
||||
"But map keys need not be keywords"
|
||||
"Ключи — не обязательно ключевые слова"
|
||||
(= __ ({2010 "Vancouver" 2014 "Sochi" 2018 "PyeongChang"} 2014))
|
||||
|
||||
"You may not be able to find an entry for a key"
|
||||
"Иногда — ни ключа, ни значения"
|
||||
(= __ (get {:a 1 :b 2} :c))
|
||||
|
||||
"But you can provide your own default"
|
||||
"На такой случай можно задать что-нибудь на свой вкус"
|
||||
(= __ (get {:a 1 :b 2} :c :key-not-found))
|
||||
|
||||
"You can find out if a key is present"
|
||||
"Есть ли ключ?"
|
||||
(= __ (contains? {:a nil :b nil} :b))
|
||||
|
||||
"Or if it is missing"
|
||||
"Или нет"
|
||||
(= __ (contains? {:a nil :b nil} :c))
|
||||
|
||||
"Maps are immutable, but you can create a new and improved version"
|
||||
"Отображения неизменяемы — с новыми элементами только новые отображения"
|
||||
(= {1 "January" 2 __} (assoc {1 "January"} 2 "February"))
|
||||
|
||||
"You can also create a new version with an entry removed"
|
||||
"И при удалении элементов возвращается новое отображение"
|
||||
(= {__ __} (dissoc {1 "January" 2 "February"} 2))
|
||||
|
||||
"Create a new map by merging"
|
||||
"И при совмещении"
|
||||
(= {:a 1 :b 2 __ __} (merge {:a 1 :b 2} {:c 3}))
|
||||
|
||||
"Specify how to handle entries with same keys when merging"
|
||||
"Можно указать как быть со значениями идентичных ключей"
|
||||
(= {:a 1 :b __ :c 3} (merge-with + {:a 1 :b 1} {:b 1 :c 3}))
|
||||
|
||||
"Often you will need to get the keys, but the order is undependable"
|
||||
"Внутри ничего не сортируется. Сортировка по ключам"
|
||||
(= (list __ __ __)
|
||||
(sort (keys { 2014 "Sochi" 2018 "PyeongChang" 2010 "Vancouver"})))
|
||||
|
||||
"You can get the values in a similar way"
|
||||
"По значениям"
|
||||
(= (list __ __ __)
|
||||
(sort (vals {2010 "Vancouver" 2014 "Sochi" 2018 "PyeongChang"})))
|
||||
|
||||
"You can even iterate over the map entries as a seq"
|
||||
"Ключ и значение идут друг за другом"
|
||||
(= {:a __ :b __}
|
||||
(into {}
|
||||
(map
|
||||
|
|
|
|||
|
|
@ -7,34 +7,34 @@
|
|||
(defn square [n] (* n n))
|
||||
|
||||
(meditations
|
||||
"Calling a function is like giving it a hug with parentheses"
|
||||
"Вызываем функцию «обнимая» её скобками"
|
||||
(= __ (square 9))
|
||||
|
||||
"Functions are usually defined before they are used"
|
||||
"Сначала нужно её создать"
|
||||
(= __ (multiply-by-ten 2))
|
||||
|
||||
"But they can also be defined inline"
|
||||
"Или использовать анонимную"
|
||||
(= __ ((fn [n] (* 5 n)) 2))
|
||||
|
||||
"Or using an even shorter syntax"
|
||||
"Clojure упрощает жизнь и запись анонимных функций"
|
||||
(= __ (#(* 15 %) 4))
|
||||
|
||||
"Even anonymous functions may take multiple arguments"
|
||||
"Аргументов — сколько угодно!"
|
||||
(= __ (#(+ %1 %2 %3) 4 5 6))
|
||||
|
||||
"Arguments can also be skipped"
|
||||
"Их даже можно не учитывать"
|
||||
(= __ (#(str "AA" %2) "bb" "CC"))
|
||||
|
||||
"One function can beget another"
|
||||
"Функция может возвращать функцию"
|
||||
(= 9 (((fn [] ___)) 4 5))
|
||||
|
||||
"Functions can also take other functions as input"
|
||||
"Может принимать её в качестве аргумента"
|
||||
(= 20 ((fn [f] (f 4 5))
|
||||
___))
|
||||
|
||||
"Higher-order functions take function arguments"
|
||||
"Функции высшего порядка так и делают"
|
||||
(= 25 (___
|
||||
(fn [n] (* n n))))
|
||||
|
||||
"But they are often better written using the names of functions"
|
||||
"Хотя, иногда неплохо создать функцию заранее, а не создавать анонимную"
|
||||
(= 25 (___ square)))
|
||||
|
|
|
|||
|
|
@ -9,39 +9,39 @@
|
|||
"is that even exercise?"))
|
||||
|
||||
(meditations
|
||||
"You will face many decisions"
|
||||
"Нужно принимать решения"
|
||||
(= __ (if (false? (= 4 5))
|
||||
:a
|
||||
:b))
|
||||
|
||||
"Some of them leave you no alternative"
|
||||
"Иногда альтернативы нет"
|
||||
(= __ (if (> 4 3)
|
||||
[]))
|
||||
|
||||
"And in such a situation you may have nothing"
|
||||
"И вы ничего не получаете"
|
||||
(= __ (if (nil? 0)
|
||||
[:a :b :c]))
|
||||
|
||||
"In others your alternative may be interesting"
|
||||
"Иногда выбор есть"
|
||||
(= :glory (if (not (empty? ()))
|
||||
:doom
|
||||
__))
|
||||
|
||||
"You may have a multitude of possible paths"
|
||||
"И вариантов много"
|
||||
(let [x 5]
|
||||
(= :your-road (cond (= x __) :road-not-taken
|
||||
(= x __) :another-road-not-taken
|
||||
:else __)))
|
||||
|
||||
"Or your fate may be sealed"
|
||||
"Получаем doom"
|
||||
(= 'doom (if-not (zero? __)
|
||||
'doom
|
||||
'more-doom))
|
||||
|
||||
"In case of emergency, go fast"
|
||||
"Выбирать можно и так"
|
||||
(= "pretty fast"
|
||||
(explain-exercise-velocity __))
|
||||
|
||||
"But admit it when you don't know what to do"
|
||||
"Можно задавать ответ по-умолчанию"
|
||||
(= __
|
||||
(explain-exercise-velocity :watching-tv)))
|
||||
|
|
|
|||
|
|
@ -2,34 +2,34 @@
|
|||
(:require [koan-engine.core :refer :all]))
|
||||
|
||||
(meditations
|
||||
"The map function relates a sequence to another"
|
||||
"Создаём номую последовательность изменяя данную"
|
||||
(= [__ __ __] (map (fn [x] (* 4 x)) [1 2 3]))
|
||||
|
||||
"You may create that mapping"
|
||||
"Изменяйте, создаваю свои функции"
|
||||
(= [1 4 9 16 25] (map (fn [x] __) [1 2 3 4 5]))
|
||||
|
||||
"Or use the names of existing functions"
|
||||
"Или используйте существующие"
|
||||
(= __ (map nil? [:a :b nil :c :d]))
|
||||
|
||||
"A filter can be strong"
|
||||
"Такой фильтр не пропустит ничего"
|
||||
(= __ (filter (fn [x] false) '(:anything :goes :here)))
|
||||
|
||||
"Or very weak"
|
||||
"А такой?"
|
||||
(= __ (filter (fn [x] true) '(:anything :goes :here)))
|
||||
|
||||
"Or somewhere in between"
|
||||
"Какой фильтр здесь?"
|
||||
(= [10 20 30] (filter (fn [x] __) [10 20 30 40 50 60 70 80]))
|
||||
|
||||
"Maps and filters may be combined"
|
||||
"Сначала фильтруем, потом изменяем полученное"
|
||||
(= [10 20 30] (map (fn [x] __) (filter (fn [x] __) [1 2 3 4 5 6 7 8])))
|
||||
|
||||
"Reducing can increase the result"
|
||||
"Уменьшаем объём, увеличиваем значение"
|
||||
(= __ (reduce (fn [a b] (* a b)) [1 2 3 4]))
|
||||
|
||||
"You can start somewhere else"
|
||||
"Можно указать начальное значение"
|
||||
(= 2400 (reduce (fn [a b] (* a b)) __ [1 2 3 4]))
|
||||
|
||||
"Numbers are not the only things one can reduce"
|
||||
"Не только числа"
|
||||
(= "longest" (reduce (fn [a b]
|
||||
(if (< __ __) b a))
|
||||
["which" "word" "is" "longest"])))
|
||||
|
|
|
|||
|
|
@ -15,28 +15,28 @@
|
|||
(defmethod diet :default [a] __)
|
||||
|
||||
(meditations
|
||||
"Some functions can be used in different ways - with no arguments"
|
||||
"Полиморфизм. Без аргументов."
|
||||
(= __ (hello))
|
||||
|
||||
"With one argument"
|
||||
"Один аргумент"
|
||||
(= __ (hello "world"))
|
||||
|
||||
"Or with many arguments"
|
||||
"Тысячи их"
|
||||
(= __
|
||||
(hello "Peter" "Paul" "Mary"))
|
||||
|
||||
"Multimethods allow more complex dispatching"
|
||||
"Мультиметоды и диспетчеризация. Всё просто."
|
||||
(= "Bambi eats veggies."
|
||||
(diet {:species "deer" :name "Bambi" :age 1 :eater :herbivore}))
|
||||
|
||||
"Animals have different names"
|
||||
"Имена разные"
|
||||
(= "Thumper eats veggies."
|
||||
(diet {:species "rabbit" :name "Thumper" :age 1 :eater :herbivore}))
|
||||
|
||||
"Different methods are used depending on the dispatch function result"
|
||||
"Разные методы исходя из вывода"
|
||||
(= "Simba eats animals."
|
||||
(diet {:species "lion" :name "Simba" :age 1 :eater :carnivore}))
|
||||
|
||||
"You may use a default method when no others match"
|
||||
"Традиционно, есть и метод по-умолчанию"
|
||||
(= "I don't know what Rich Hickey eats."
|
||||
(diet {:name "Rich Hickey"})))
|
||||
|
|
|
|||
|
|
@ -2,27 +2,27 @@
|
|||
(:require [koan-engine.core :refer :all]))
|
||||
|
||||
(meditations
|
||||
"There are many ways to generate a sequence"
|
||||
"Создаём последовательность"
|
||||
(= __ (range 1 5))
|
||||
|
||||
"The range starts at the beginning by default"
|
||||
"От нуля до …"
|
||||
(= __ (range 5))
|
||||
|
||||
"Only take what you need when the sequence is large"
|
||||
"Ленивые вычисления — взять только то что надо"
|
||||
(= [0 1 2 3 4 5 6 7 8 9]
|
||||
(take __ (range 100)))
|
||||
|
||||
"Or limit results by dropping what you don't need"
|
||||
"Не брать того что не нужно, да и не хочется"
|
||||
(= [95 96 97 98 99]
|
||||
(drop __ (range 100)))
|
||||
|
||||
"Iteration provides an infinite lazy sequence"
|
||||
"Если не указать сколько взять, можно переполнить стек. Такая функция."
|
||||
(= __ (take 8 (iterate (fn [x] (* x 2)) 1)))
|
||||
|
||||
"Repetition is key"
|
||||
"Повтор"
|
||||
(= [:a :a :a :a :a :a :a :a :a :a]
|
||||
(repeat 10 __))
|
||||
|
||||
"Iteration can be used for repetition"
|
||||
"Результат идентичен"
|
||||
(= (repeat 100 "hello")
|
||||
(take 100 (iterate ___ "hello"))))
|
||||
|
|
|
|||
Loading…
Reference in a new issue