diff options
Diffstat (limited to 'ru-ru')
| -rw-r--r-- | ru-ru/asymptotic-notation-ru.html.markdown | 450 | ||||
| -rw-r--r-- | ru-ru/bash-ru.html.markdown | 346 | ||||
| -rw-r--r-- | ru-ru/c++-ru.html.markdown | 7 | ||||
| -rw-r--r-- | ru-ru/clojure-ru.html.markdown | 52 | ||||
| -rw-r--r-- | ru-ru/common-lisp-ru.html.markdown | 704 | ||||
| -rw-r--r-- | ru-ru/crystal-ru.html.markdown | 584 | ||||
| -rw-r--r-- | ru-ru/jquery-ru.html.markdown | 127 | ||||
| -rw-r--r-- | ru-ru/kotlin-ru.html.markdown | 2 | ||||
| -rw-r--r-- | ru-ru/markdown-ru.html.markdown | 55 | ||||
| -rw-r--r-- | ru-ru/php-composer-ru.html.markdown | 197 | ||||
| -rw-r--r-- | ru-ru/rust-ru.html.markdown | 316 | ||||
| -rw-r--r-- | ru-ru/yaml-ru.html.markdown | 189 | 
12 files changed, 2668 insertions, 361 deletions
| diff --git a/ru-ru/asymptotic-notation-ru.html.markdown b/ru-ru/asymptotic-notation-ru.html.markdown index 73ad80ba..7fd02c47 100644 --- a/ru-ru/asymptotic-notation-ru.html.markdown +++ b/ru-ru/asymptotic-notation-ru.html.markdown @@ -1,225 +1,225 @@ ---- -category: Algorithms & Data Structures -name: Asymptotic Notation -contributors: -    - ["Jake Prather", "http://github.com/JakeHP"] -    - ["Divay Prakash", "http://github.com/divayprakash"] -translators: -    - ["pru-mike", "http://gihub.com/pru-mike"] -lang: ru-ru ---- - -# О-cимволика - -## Что это такое? - -О-cимволика или асимптотическая запись это система символов позволяющая оценить -время выполнения алгоритма, устанавливая зависимость времени выполнения от -увеличения объема входных данных, так же известна как оценка -сложности алгоритмов. Быстро-ли алгоритм станет невероятно медленным, когда -объем входных данных увеличится? Будет-ли алгоритм выполняться достаточно быстро, -если объем входных данных возрастет? О-символика позволяет ответить на эти -вопросы. - -## Можно-ли по-другому найти ответы на эти вопросы? - -Один способ это подсчитать число элементарных операций в зависимости от -различных объемов входных данных. Хотя это и приемлемое решение, тот объем -работы которого оно потребует, даже для простых алгоритмов, делает его  -использование неоправданным. - -Другой способ это измерить какое время алгоритм потребует для завершения на -различных объемах входных данных. В тоже время, точность и относительность -(полученное время будет относиться только к той машине на которой оно -вычислено) этого метода зависит от среды выполнения: компьютерного аппаратного -обеспечения, мощности процессора и т.д. - -## Виды О-символики - -В первом разделе этого документа мы определили, что О-символика -позволяет оценивать алгоритмы в зависимости от изменения размера входных -данных. Представим что алгоритм это функция f, n размер входных данных и  -f(n) время выполнения. Тогда для данного алгоритма f c размером входных -данных n получим какое-то результирующее время выполнения f(n). -Из этого можно построить график, где ось Y время выполнения, ось X размер входных -данных и точки на графике это время выполнения для заданного размера входных -данных. - -С помощью О-символики можно оценить функцию или алгоритм -несколькими различными способами. Например можно оценить алгоритм исходя -из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается -анализ на основе верхней оценки. Как правило не используется нижняя оценка, -потому что она не подходит под планируемые условия. Отличный пример алгоритмы -сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка -большинства таких алгоритмов может быть дана как одна операция. В то время как в -большинстве случаев, добавляемые элементы должны быть отсортированы -соответствующим образом при помощи дерева, что может потребовать обхода целой -ветви. Это и есть худший случай, для которого планируется верхняя оценка. - -### Виды функций, пределы и упрощения - -``` -Логарифмическая функция - log n -Линейная функция - an + b -Квадратическая функция - an^2 + bn +c -Полиномиальная функция - an^z + . . . + an^2 + a*n^1 + a*n^0, где z константа -Экспоненциальная функция - a^n, где a константа -``` - -Приведены несколько базовых функций используемых при определении сложности в -различных оценках. Список начинается с самой медленно возрастающей функции -(логарифм, наиболее быстрое время выполнения) и следует до самой быстро -возрастающей функции (экспонента, самое медленное время выполнения). Отметим, -что в то время как 'n' или размер входных данных, возрастает в каждой из этих функций, -результат намного быстрее возрастает в квадратической, полиномиальной -и экспоненциальной по сравнению с логарифмической и линейной. - -Крайне важно понимать, что при использовании описанной далее нотации необходимо -использовать упрощенные выражения. -Это означает, что необходимо отбрасывать константы и слагаемые младших порядков, -потому что если размер входных данных (n в функции f(n) нашего примера) -увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков -и константы становятся пренебрежительно малыми. Таким образом, если есть -константа например размера 2^9001 или любого другого невообразимого размера, -надо понимать, что её упрощение внесёт значительные искажения в точность -оценки. - -Т.к. нам нужны упрощенные выражения, немного скорректируем нашу таблицу... - -``` -Логарифм - log n -Линейная функция - n -Квадратическая функция - n^2 -Полиномиальная функция - n^z, где z константа -Экспонента - a^n, где a константа -``` - -### О-Большое -О-Большое, записывается как **О**, это асимптотическая запись для оценки худшего -случая или для ограничения заданой функции сверху. Это позволяет сделать  -_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения  -алгоритма. Допустим `f(n)` время выполнения алгоритма и `g(n)` заданная временная -сложность которая проверяется для алгоритма. Тогда `f(n)` это O(g(n)), если -существуют действительные константы с (с > 0) и n<sub>0</sub>, такие -что `f(n)` <= `c g(n)` выполняется для всех n начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>). - -*Пример 1* - -``` -f(n) = 3log n + 100 -g(n) = log n -``` - -Является-ли `f(n)` O(g(n))? -Является-ли `3 log n + 100` O(log n)? -Посмотрим на определение О-Большого: - -``` -3log n + 100 <= c * log n -``` - -Существуют-ли константы c, n<sub>0</sub> такие что выражение верно для всех n > n<sub>0</sub> - -``` -3log n + 100 <= 150 * log n, n > 2 (неопределенно для n = 1) -``` - -Да! По определению О-Большого `f(n)` является O(g(n)). - -*Пример 2* - -``` -f(n) = 3 * n^2 -g(n) = n -``` - -Является-ли `f(n)` O(g(n))? -Является-ли `3 * n^2` O(n)? -Посмотрим на определение О-Большого: - -``` -3 * n^2 <= c * n -``` - -Существуют-ли константы c, n<sub>0</sub> такие что выражение верно для всех n > n<sub>0</sub>? -Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)). - -### Омега-Большое -Омега-Большое, записывается как **Ω**, это асимптотическая запись для оценки -лучшего случая или для ограничения заданой функции снизу. Это позволяет сделать -_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения  -алгоритма.  - -`f(n)` принадлежит Ω(g(n)), если существуют действительные константы -с (с > 0) и <sub>0</sub> (n<sub>0</sub> > 0), такие что `f(n)` >= `c g(n)` для всех n > n<sub>0</sub>. - -### Примечание - -Асимптотические оценки сделаные при помощи О-Большое и Омега-Большое могут -как быть так и не быть точными. Для того что бы обозначить что границы не -являются асимптотически точными используются записи о-малое и омега-малое. - -### О-Малое -O-Малое, записывается как **о**, это асимптотическая запись для оценки верхней -границы времени выполнения алгоритма, при условии что граница не является -асимптотически точной. - -`f(n)` является o(g(n)), если можно подобрать такие действительные константы, -что для всех c (c > 0) найдется n<sub>0</sub> (n<sub>0</sub> > 0), так -что `f(n)` < `c g(n)` выполняется для всех n (n > n<sub>0</sub>). - -Определения О-символики для О-Большое и О-Малое похожи. Главное отличие в том, -что если f(n) = O(g(n)), тогда условие f(n) <= c g(n) выполняется если _**существует**_ -константа c > 0, но если f(n) = o(g(n)), тогда условие f(n) < c g(n) выполняется -для _**всех**_ констант с > 0. - -### Омега-малое -Омега-малое, записывается как **ω**, это асимптотическая запись для оценки -верней границы времени выполнения алгоритма, при условии что граница не является -асимптотически точной. - -`f(n)` является ω(g(n)), если можно подобрать такие действительные константы, -что для всех c (c > 0) найдется n<sub>0</sub> (n<sub>0</sub> > 0), так -что `f(n)` > `c g(n)` выполняется для всех n (n > n<sub>0</sub>) - -Определения Ω-символики и ω-символики похожи. Главное отличие в том, что -если f(n) = Ω(g(n)), тогда условие f(n) >= c g(n) выполняется если _**существует**_ -константа c > 0, но если f(n) = ω(g(n)), тогда условие f(n) > c g(n) -выполняется для _**всех**_ констант с > 0. - -### Тета -Тета, записывается как **Θ**, это асимптотическая запись для оценки -_***асимптотически точной границы***_ времени выполнения алгоритма. - -`f(n)` является Θ(g(n)), если для некоторых действительных -констант c1, c2 и n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0), -`c1 g(n)` < `f(n)` < `c2 g(n)` для всех n (n > n<sub>0</sub>). - -∴ `f(n)` является Θ(g(n)) означает что `f(n)` является O(g(n)) -и `f(n)` является Ω(g(n)). - -О-Большое основной инструмент для анализа сложности алгоритмов. -Так же смотрите примеры по ссылкам. - -### Заключение -Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и -посмотреть дополнительную литературу. В них дается более глубокое описание с -определениями и примерами. - - -## Дополнительная литература - -* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/) -* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/) - -## Ссылки - -* [Оценки времени исполнения. Cимвол O()](http://algolist.manual.ru/misc/o_n.php) -* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903) - -## Ссылки (Eng) - -* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1) -* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf) -* [Cheatsheet 2](http://bigocheatsheet.com/) - +---
 +category: Algorithms & Data Structures
 +name: Asymptotic Notation
 +contributors:
 +    - ["Jake Prather", "http://github.com/JakeHP"]
 +    - ["Divay Prakash", "http://github.com/divayprakash"]
 +translators:
 +    - ["pru-mike", "http://github.com/pru-mike"]
 +lang: ru-ru
 +---
 +
 +# О-символика
 +
 +## Что это такое?
 +
 +О-символика, или асимптотическая запись, — это система символов, позволяющая
 +оценить время выполнения алгоритма, устанавливая зависимость времени выполнения
 +от увеличения объёма входных данных. Она также известна как оценка
 +сложности алгоритмов. Станет ли алгоритм невероятно медленным, когда
 +объём входных данных увеличится? Будет ли алгоритм выполняться достаточно быстро,
 +если объём входных данных возрастёт? О-символика позволяет ответить на эти
 +вопросы.
 +
 +## Можно ли по-другому найти ответы на эти вопросы?
 +
 +Один способ — это подсчитать число элементарных операций в зависимости от
 +различных объёмов входных данных. Хотя это и приемлемое решение, тот объём
 +работы, которого оно потребует, даже для простых алгоритмов делает его 
 +использование неоправданным.
 +
 +Другой способ — это измерить, какое время алгоритм потребует для завершения на
 +различных объёмах входных данных. В то же время, точность и относительность
 +этого метода (полученное время будет относиться только к той машине, на которой 
 +оно вычислено) зависит от среды выполнения: компьютерного аппаратного
 +обеспечения, мощности процессора и т.д.
 +
 +## Виды О-символики
 +
 +В первом разделе этого документа мы определили, что О-символика
 +позволяет оценивать алгоритмы в зависимости от изменения размера входных
 +данных. Представим, что алгоритм — это функция f, n — размер входных данных и 
 +f(n) — время выполнения. Тогда для данного алгоритма f с размером входных
 +данных n получим какое-то результирующее время выполнения f(n).
 +Из этого можно построить график, где ось y — время выполнения, ось x — размер входных
 +данных, а точки на графике — это время выполнения для заданного размера входных
 +данных.
 +
 +С помощью О-символики можно оценить функцию или алгоритм
 +несколькими различными способами. Например, можно оценить алгоритм исходя
 +из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается
 +анализ на основе верхней оценки. Как правило не используется нижняя оценка,
 +потому что она не подходит под планируемые условия. Отличный пример — алгоритмы
 +сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка
 +большинства таких алгоритмов может быть дана как одна операция. В то время как в
 +большинстве случаев добавляемые элементы должны быть отсортированы
 +соответствующим образом при помощи дерева, что может потребовать обхода целой
 +ветви. Это и есть худший случай, для которого планируется верхняя оценка.
 +
 +### Виды функций, пределы и упрощения
 +
 +```
 +Логарифмическая функция — log n
 +Линейная функция — an + b
 +Квадратичная функция — an^2 + bn +c
 +Степенная функция — an^z + . . . + an^2 + a*n^1 + a*n^0, где z — константа
 +Показательная функция — a^n, где a — константа
 +```
 +
 +Приведены несколько базовых функций, используемых при определении сложности в
 +различных оценках. Список начинается с самой медленно возрастающей функции
 +(логарифм, наиболее быстрое время выполнения) и следует до самой быстро
 +возрастающей функции (экспонента, самое медленное время выполнения). Отметим,
 +что в то время, как «n», или размер входных данных, возрастает в каждой из этих функций,
 +результат намного быстрее возрастает в квадратичной, степенной
 +и показательной по сравнению с логарифмической и линейной.
 +
 +Крайне важно понимать, что при использовании описанной далее нотации необходимо
 +использовать упрощённые выражения.
 +Это означает, что необходимо отбрасывать константы и слагаемые младших порядков,
 +потому что если размер входных данных (n в функции f(n) нашего примера)
 +увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков
 +и константы становятся пренебрежительно малыми. Таким образом, если есть
 +константа, например, размера 2^9001 или любого другого невообразимого размера,
 +надо понимать, что её упрощение внесёт значительные искажения в точность
 +оценки.
 +
 +Т.к. нам нужны упрощённые выражения, немного скорректируем нашу таблицу...
 +
 +```
 +Логарифм — log n
 +Линейная функция — n
 +Квадратичная функция — n^2
 +Степенная функция — n^z, где z — константа
 +Показательная функция — a^n, где a — константа
 +```
 +
 +### О Большое
 +О Большое, записывается как **О**, — это асимптотическая запись для оценки худшего
 +случая, или для ограничения заданной функции сверху. Это позволяет сделать 
 +_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения 
 +алгоритма. Пусть `f(n)` — время выполнения алгоритма, а `g(n)` — заданная временная
 +сложность, которая проверяется для алгоритма. Тогда `f(n)` — это O(g(n)), если
 +существуют действительные константы c (c > 0) и n<sub>0</sub>, такие,
 +что `f(n)` <= `c g(n)` выполняется для всех n, начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>).
 +
 +*Пример 1*
 +
 +```
 +f(n) = 3log n + 100
 +g(n) = log n
 +```
 +
 +Является ли `f(n)` O(g(n))?
 +Является ли `3 log n + 100` O(log n)?
 +Посмотрим на определение О Большого:
 +
 +```
 +3log n + 100 <= c * log n
 +```
 +
 +Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
 +
 +```
 +3log n + 100 <= 150 * log n, n > 2 (не определенно для n = 1)
 +```
 +
 +Да! По определению О Большого `f(n)` является O(g(n)).
 +
 +*Пример 2*
 +
 +```
 +f(n) = 3 * n^2
 +g(n) = n
 +```
 +
 +Является ли `f(n)` O(g(n))?
 +Является ли `3 * n^2` O(n)?
 +Посмотрим на определение О Большого:
 +
 +```
 +3 * n^2 <= c * n
 +```
 +
 +Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
 +Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)).
 +
 +### Омега Большое
 +Омега Большое, записывается как **Ω**, — это асимптотическая запись для оценки
 +лучшего случая, или для ограничения заданной функции снизу. Это позволяет сделать
 +_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения 
 +алгоритма. 
 +
 +`f(n)` является Ω(g(n)), если существуют действительные константы
 +c (c > 0) и n<sub>0</sub> (n<sub>0</sub> > 0), такие, что `f(n)` >= `c g(n)` для всех n > n<sub>0</sub>.
 +
 +### Примечание
 +
 +Асимптотические оценки, сделаные при помощи О Большого и Омега Большого, могут
 +как являться, так и не являться точными. Для того, чтобы обозначить, что границы не
 +являются асимптотически точными, используются записи О Малое и Омега Малое.
 +
 +### О Малое
 +O Малое, записывается как **о**, — это асимптотическая запись для оценки верхней
 +границы времени выполнения алгоритма при условии, что граница не является
 +асимптотически точной.
 +
 +`f(n)` является o(g(n)), если можно подобрать такие действительные константы,
 +что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
 +что `f(n)` < `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
 +
 +Определения О-символики для О Большого и О Малого похожи. Главное отличие в том,
 +что если f(n) = O(g(n)), тогда условие f(n) <= c g(n) выполняется, если _**существует**_
 +константа c > 0, но если f(n) = o(g(n)), тогда условие f(n) < c g(n) выполняется
 +для _**всех**_ констант c > 0.
 +
 +### Омега Малое
 +Омега Малое, записывается как **ω**, — это асимптотическая запись для оценки
 +верхней границы времени выполнения алгоритма при условии, что граница не является
 +асимптотически точной.
 +
 +`f(n)` является ω(g(n)), если можно подобрать такие действительные константы,
 +что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
 +что `f(n)` > `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
 +
 +Определения Ω-символики и ω-символики похожи. Главное отличие в том, что
 +если f(n) = Ω(g(n)), тогда условие f(n) >= c g(n) выполняется, если _**существует**_
 +константа c > 0, но если f(n) = ω(g(n)), тогда условие f(n) > c g(n)
 +выполняется для _**всех**_ констант c > 0.
 +
 +### Тета
 +Тета, записывается как **Θ**, — это асимптотическая запись для оценки
 +_***асимптотически точной границы***_ времени выполнения алгоритма.
 +
 +`f(n)` является Θ(g(n)), если для некоторых действительных
 +констант c1, c2 и n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0)
 +`c1 g(n)` < `f(n)` < `c2 g(n)` для всех n (n > n<sub>0</sub>).
 +
 +∴ `f(n)` является Θ(g(n)) означает, что `f(n)` является O(g(n))
 +и `f(n)` является Ω(g(n)).
 +
 +О Большое — основной инструмент для анализа сложности алгоритмов.
 +Также см. примеры по ссылкам.
 +
 +### Заключение
 +Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и
 +посмотреть дополнительную литературу. В ней даётся более глубокое описание с
 +определениями и примерами.
 +
 +
 +## Дополнительная литература
 +
 +* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/)
 +* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/)
 +
 +## Ссылки
 +
 +* [Оценки времени исполнения. Символ O()](http://algolist.manual.ru/misc/o_n.php)
 +* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903)
 +
 +## Ссылки (англ.)
 +
 +* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1)
 +* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf)
 +* [Cheatsheet 2](http://bigocheatsheet.com/)
 +
 diff --git a/ru-ru/bash-ru.html.markdown b/ru-ru/bash-ru.html.markdown index 5e99afc2..ce918340 100644 --- a/ru-ru/bash-ru.html.markdown +++ b/ru-ru/bash-ru.html.markdown @@ -11,29 +11,40 @@ contributors:      - ["Rahil Momin", "https://github.com/iamrahil"]      - ["Gregrory Kielian", "https://github.com/gskielian"]      - ["Etan Reisner", "https://github.com/deryni"] +    - ["Jonathan Wang", "https://github.com/Jonathansw"]    +    - ["Leo Rudberg", "https://github.com/LOZORD"] +    - ["Betsy Lorton", "https://github.com/schbetsy"] +    - ["John Detter", "https://github.com/jdetter"] +    - ["Harry Mumford-Turner", "https://github.com/harrymt"] +    - ["Martin Nicholson", "https://github.com/mn113"]  translators:      - ["Andrey Samsonov", "https://github.com/kryzhovnik"] -    - ["Andre Polykanine", "https://github.com/Oire"] +    - ["Andre Polykanine", "https://github.com/Menelion"]  filename: LearnBash-ru.sh  lang: ru-ru  --- -Bash - это командная оболочка unix (unix shell), которая распространялась как оболочка для операционной системы GNU и используется в качестве оболочки по умолчанию для Linux и Mac OS X. -Почти все нижеприведенные примеры могут быть частью shell-скриптов или исполнены напрямую в shell. +Bash — это командная оболочка unix, которая распространялась как оболочка +для операционной системы GNU и используется в качестве оболочки по умолчанию +для Linux и Mac OS X. +Почти все нижеприведённые примеры могут быть частью shell-скриптов +или исполнены напрямую в shell.  [Подробнее.](http://www.gnu.org/software/bash/manual/bashref.html)  ```bash  #!/bin/bash -# Первая строка скрипта - это shebang, который сообщает системе, как исполнять -# этот скрипт: http://en.wikipedia.org/wiki/Shebang_(Unix) -# Как вы уже поняли, комментарии начинаются с #. Shebang - тоже комментарий. +# Первая строка скрипта — это шебанг, который сообщает системе, как исполнять +# этот скрипт: https://ru.wikipedia.org/wiki/Шебанг_(Unix) +# Как вы уже поняли, комментарии начинаются с «#». Шебанг — тоже комментарий.  # Простой пример hello world:  echo Hello world!  # Отдельные команды начинаются с новой строки или разделяются точкой с запятой:  echo 'Это первая строка'; echo 'Это вторая строка' +# => Это первая строка +# => Это вторая строка  # Вот так объявляется переменная:  VARIABLE="Просто строка" @@ -41,103 +52,234 @@ VARIABLE="Просто строка"  # но не так:  VARIABLE = "Просто строка"  # Bash решит, что VARIABLE - это команда, которую он должен исполнить, -# и выдаст ошибку, потому что не сможет найти ее. +# и выдаст ошибку, потому что не сможет найти её.  # и не так:  VARIABLE= 'Просто строка' -# Тут Bash решит, что 'Просто строка' - это команда, которую он должен исполнить, -# и выдаст ошибку, потому что не сможет найти такой команды +# Тут Bash решит, что 'Просто строка' — это команда, которую он должен +# исполнить, и выдаст ошибку, потому что не сможет найти такой команды  # (здесь 'VARIABLE=' выглядит как присвоение значения переменной,  # но только в контексте исполнения команды 'Просто строка').  # Использование переменой: -echo $VARIABLE -echo "$VARIABLE" -echo '$VARIABLE' -# Когда вы используете переменную - присваиваете, экспортируете и т.д. - +echo $VARIABLE # => Просто строка +echo "$VARIABLE" # => Просто строка +echo '$VARIABLE' # => $Variable +# Когда вы используете переменную — присваиваете, экспортируете и т.д. —  # пишите её имя без $. А для получения значения переменной используйте $.  # Заметьте, что ' (одинарные кавычки) не раскрывают переменные в них. -# Подстановка строк в переменные -echo ${VARIABLE/Просто/A} -# Это выражение заменит первую встреченную подстроку "Просто" на "A" +# Раскрытие параметров ${ }: +echo ${Variable} # => Просто строка +# Это простое использование раскрытия параметров +# Раскрытие параметров получает значение переменной. +# Оно «раскрывает», или печатает это значение. +# ̶Значение можно изменить во время раскрытия. +# Ниже приведены другие модификации при раскрытии параметров. + +# Замена подстрок в переменных +echo ${Variable/Просто/Это} # => Это строка +# Заменит первое вхождение «Просто» на «Это»  # Взять подстроку из переменной  LENGTH=7 -echo ${VARIABLE:0:LENGTH} -# Это выражение вернет только первые 7 символов переменной VARIABLE +echo ${VARIABLE:0:LENGTH} # => Просто  +# Это выражение вернёт только первые 7 символов переменной VARIABLE +echo ${Variable: -5} # => трока +# Вернёт последние 5 символов (обратите внимание на пробел перед «-5») + +# Длина строки +echo ${#Variable} # => 13 -# Значение по умолчанию -echo ${FOO:-"DefaultValueIfFOOIsMissingOrEmpty"} +# Значение переменной по умолчанию +echo ${FOO:-"ЗначениеПоУмолчаниюЕслиFooПустаИлиНеНайдена"} +# => ЗначениеПоУмолчаниюЕслиFooПустаИлиНеНайдена  # Это сработает при отсутствующем значении (FOO=) и пустой строке (FOO=""); -# ноль (FOO=0) вернет 0. -# Заметьте, что в любом случае значение самой переменной FOO не изменится. +# ноль (FOO=0) вернёт 0. +# Заметьте, что в любом случае это лишь вернёт значение по умолчанию, +# а значение самой переменной FOO не изменится. + +# Объявить массив из 6 элементов +array0=(один два три четыре пять шесть) +# Вывести первый элемент +echo $array0 # => "один" +# Вывести первый элемент +echo ${array0[0]} # => "один" +# Вывести все элементы +echo ${array0[@]} # => "один два три четыре пять шесть" +# Вывести число элементов +echo ${#array0[@]} # => "6" +# Вывести число символов в третьем элементе +echo ${#array0[2]} # => "3" +# Вывести 2 элемента, начиная с четвёртого +echo ${array0[@]:3:2} # => "четыре пять" +# Вывести все элементы, каждый на своей строке +for i in "${array0[@]}"; do +    echo "$i" +done + +# Раскрытие скобок { } +# Используется для создания произвольных строк +echo {1..10} # => 1 2 3 4 5 6 7 8 9 10 +echo {a..z} # => a b c d e f g h i j k l m n o p q r s t u v w x y z +# Выведет диапазон от начального до конечного значения  # Встроенные переменные:  # В bash есть полезные встроенные переменные, например -echo "Последнее возвращенное значение: $?" -echo "PID скрипта: $$" -echo "Количество аргументов: $#" -echo "Аргументы скрипта: $@" +echo "Значение, возвращённое последней программой: $?" +echo "Идентификатор процесса скрипта: $$" +echo "Число аргументов, переданных скрипту: $#" +echo "Все аргументы, переданные скрипту: $@"  echo "Аргументы скрипта, распределённые по отдельным переменным: $1 $2..." -# Чтение аргументов из устройста ввода: +# Теперь, когда мы знаем, как выводить и использовать переменные, +# давайте изучим некоторые другие основы Bash! + +# Текущая директория доступна по команде `pwd`. +# `pwd` расшифровывается как «print working directory», т.е. +# «напечатать рабочую директорию». +# Мы также можем использовать встроенную переменную `$PWD`. +# Заметьте, следующие выражения эквивалентны: +echo "Я в $(pwd)" # выполняет `pwd` и раскрывает вывод +echo "Я в $PWD" # раскрывает переменную + +# Если вы получаете слишком много информации в терминале или из скрипта, +# команда `clear` очистит экран +clear +# Очистить экран можно также с помощью Ctrl+L + +# Чтение аргументов с устройства ввода:  echo "Как Вас зовут?"  read NAME # Обратите внимание, что нам не нужно определять новую переменную  echo Привет, $NAME!  # У нас есть обычная структура if:  # наберите 'man test' для получения подробной информации о форматах условия -if [ $NAME -ne $USER ] +if [ $NAME != $USER ]  then      echo "Имя не совпадает с именем пользователя"  else      echo "Имя совпадает с именем пользователя"  fi +# Истинно, если значение $Name не совпадает с текущим именем пользователя -# Примечание: если $Name пустой, bash интерпретирует код как: -if [ -ne $USER ] +# Примечание: если $Name пуста, bash интерпретирует код так: +if [ != $USER ]  # а это ошибочная команда -# поэтому такие переменные нужно использовать так: -if [ "$Name" -ne $USER ] ... -# когда $Name пустой, bash видит код как: -if [ "" -ne $USER ] ... +# поэтому «безопасный» способ использовать пустые переменные в Bash таков: +if [ "$Name" != $USER ] ... +# при этом, когда $Name пуста, bash видит код так: +if [ "" != $USER ] ...  # что работает правильно  # Также есть условное исполнение  echo "Исполнится всегда" || echo "Исполнится, если первая команда завершится ошибкой" +# => Исполнится всегда  echo "Исполнится всегда" && echo "Исполнится, если первая команда выполнится удачно" +# => Исполнится всегда +# => Исполнится, если первая команда выполнится удачно -# Можно использовать && и || в выражениях if, когда нужно несколько пар скобок: -if [ $NAME == "Steve" ] && [ $AGE -eq 15 ] + +# Чтобы использовать && и || в выражениях if, нужно несколько пар скобок: +if [ $NAME == "Стив" ] && [ $AGE -eq 15 ] +then +    echo "Исполнится, если $NAME равно Стив И $AGE равно 15." +fi + +if [ $NAME == "Дания" ] || [ $NAME == "Зак" ]  then -    echo "Исполнится, если $NAME равно Steve И $AGE равно 15." +    echo "Исполнится, если $NAME равно Дания ИЛИ Зак."  fi -if [ $NAME == "Daniya" ] || [ $NAME == "Zach" ] +# Есть ещё оператор «=~», который проверяет строку +# на соответствие регулярному выражению: +Email=me@example.com +if [[ "$Email" =~ [a-z]+@[a-z]{2,}\.(com|net|org) ]]  then -    echo "Исполнится, если $NAME равно Daniya ИЛИ Zach." +    echo "адрес корректный!"  fi +# Обратите внимание, что =~ работает только внутри +# двойных квадратных скобок [[ ]], +# которые несколько отличаются от одинарных скобок [ ]. +# Для более подробной информации см. http://www.gnu.org/software/bash/manual/bashref.html#Conditional-Constructs. + +# Переопределить команду «ping» как псевдоним для отправки только пяти пакетов +alias ping='ping -c 5' +# Экранировать псевдоним и использовать команду под своим именем вместо него +\ping 192.168.1.1 +# Вывести все псевдонимы +alias -p  # Выражения обозначаются таким форматом: -echo $(( 10 + 5 )) +echo $(( 10 + 5 )) # => 15 -# В отличие от других языков программирования, Bash - это командная оболочка, +# В отличие от других языков программирования, Bash — это командная оболочка,  # а значит, работает в контексте текущей директории.  # Вы можете просматривать файлы и директории в текущей директории командой ls: -ls +ls # перечисляет файлы и поддиректории в текущей директории -# У этой команды есть опции: +# У этой команды есть параметры:  ls -l # Показать каждый файл и директорию на отдельной строке +ls -t # сортирует содержимое по дате последнего изменения (в обратном порядке) +ls -R # Рекурсивно выполняет `ls` по данной директории и всем её поддиректориям  # Результат предыдущей команды может быть направлен на вход следующей.  # Команда grep фильтрует ввод по шаблону. -# Так мы можем просмотреть только *.txt файлы в текущей директории: +# Так мы можем просмотреть только *.txt-файлы в текущей директории:  ls -l | grep "\.txt" +# Для вывода файлов в стандартный поток используйте `cat`: +cat file.txt + +# С помощью `cat` мы также можем читать файлы: +Contents=$(cat file.txt) +echo "НАЧАЛО ФАЙЛА\n$Contents\nКОНЕЦ ФАЙЛА" # «\n» выводит символ перевода на новую строку +# => НАЧАЛО ФАЙЛА +# => [Содержимое file.txt] +# => КОНЕЦ ФАЙЛА + +# Для копирования файлов и директорий из одного места в другое используйте `cp`. +# `cp` создаёт новые версии исходных элементов, +# так что редактирование копии не повлияет на оригинал (и наоборот). +# Обратите внимание, что команда перезапишет целевой элемент, если он уже существует. +cp srcFile.txt clone.txt +cp -r srcDirectory/ dst/ # рекурсивное копирование + +# Если вам нужно обмениваться файлами между компьютерами, посмотрите в сторону `scp` или `sftp`. +# `scp` ведёт себя очень похоже на `cp`. +# `sftp` более интерактивна. + +# Для перемещения файлов и директорий из одного места в другое используйте `mv`. +# Команда `mv` похожа на `cp`, но она удаляет исходный элемент. +# `mv` также можно использовать для переименования файлов! +mv s0urc3.txt dst.txt # Извините, тут были Leet-хакеры... + +# Поскольку Bash работает в контексте текущей директории, вам может понадобиться +# запустить команду в другой директории. +# Для изменения местоположения у нас есть `cd`: +cd ~    # Перейти в домашнюю директорию +cd      # Также переходит в домашнюю директорию +cd ..   # Перейти на уровень вверх +        # (например, из /home/username/Downloads в /home/username) +cd /home/username/Documents   # перейти в указанную директорию +cd ~/Documents/..    # Всё ещё в домашней директории. Так ведь?? +cd -    # Перейти в последнюю директорию +# => /home/username/Documents + +# Для работы по директориям используйте субоболочки +(echo "Сначала я здесь: $PWD") && (cd someDir; echo "А теперь я тут: $PWD") +pwd # всё ещё в первой директории + +# Для создания новых директорий используйте `mkdir`. +mkdir myNewDir +# Флаг `-p` указывает, что нужно создать все промежуточные директории, если нужно. +mkdir -p myNewDir/with/intermediate/directories +# Если промежуточные директории до этого не существовали, +# вышеприведённая команда без флага `-p` вернёт ошибку +  # Вы можете перенаправить ввод и вывод команды (stdin, stdout и stderr). -# Следующая команда означает: читать из stdin, пока не встретится ^EOF$, и -# перезаписать hello.py следующим строками (до строки "EOF"): +# Прочитать из stdin, пока не встретится ^EOF$, и +# перезаписать hello.py следующими строками (до строки "EOF"):  cat > hello.py << EOF  #!/usr/bin/env python  from __future__ import print_function @@ -147,23 +289,25 @@ print("#stderr", file=sys.stderr)  for line in sys.stdin:      print(line, file=sys.stdout)  EOF +# Если первый «EOF» не заключён в кавычки, переменные будут раскрыты  # Запуск hello.py с разными вариантами перенаправления потоков  # стандартных ввода, вывода и ошибок: -python hello.py < "input.in" -python hello.py > "output.out" -python hello.py 2> "error.err" -python hello.py > "output-and-error.log" 2>&1 -python hello.py > /dev/null 2>&1 +python hello.py < "input.in" # передать input.in в качестве ввода в скрипт +python hello.py > "output.out" # передать вывод скрипта в output.out +python hello.py 2> "error.err" # передать вывод ошибок в error.err +python hello.py > "output-and-error.log" 2>&1 # передать вывод скрипта и ошибок в output-and-error.log +python hello.py > /dev/null 2>&1 # передать вывод скрипта и ошибок в «чёрную дыру» /dev/null, т.е., без вывода  # Поток ошибок перезапишет файл, если этот файл существует, -# поэтому, если вы хотите дописывать файл, используйте ">>": +# поэтому, если вы хотите дописывать файл, используйте «>>»:  python hello.py >> "output.out" 2>> "error.err" -# Переписать output.txt, дописать error.err и сосчитать строки: +# Перезаписать output.txt, дописать error.err и сосчитать строки:  info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err  wc -l output.out error.err -# Запустить команду и вывести ее файловый дескриптор (смотрите: man fd) +# Запустить команду и вывести её файловый дескриптор (например, /dev/fd/123) +# См. man fd  echo <(echo "#helloworld")  # Перезаписать output.txt строкой "#helloworld": @@ -172,40 +316,49 @@ echo "#helloworld" > output.out  echo "#helloworld" | cat > output.out  echo "#helloworld" | tee output.out >/dev/null -# Подчистить временные файлы с подробным выводом ('-i' - интерактивый режим) +# Подчистить временные файлы с подробным выводом ('-i' — интерактивный режим) +# ВНИМАНИЕ: команду `rm` отменить нельзя  rm -v output.out error.err output-and-error.log +rm -r tempDir/ # рекурсивное удаление  # Команды могут быть подставлены в строку с помощью $( ):  # следующие команды выводят число файлов и директорий в текущей директории.  echo "Здесь $(ls | wc -l) элементов." -# То же самое можно сделать с использованием обратных кавычек, +# То же самое можно сделать с использованием обратных кавычек «``»,  # но они не могут быть вложенными, поэтому предпочтительно использовать $( ).  echo "Здесь `ls | wc -l` элементов."  # В Bash есть структура case, которая похожа на switch в Java и C++:  case "$VARIABLE" in  -    # Перечислите шаблоны для условий, которые хотите отловить +    # Перечислите шаблоны для условий, которые хотите выполнить      0) echo "Тут ноль.";;      1) echo "Тут один.";;      *) echo "Это не пустое значение.";;  esac -# Цикл for перебирает элементы переданные в аргументе: +# Цикл for перебирает элементы по количеству аргументов:  # Содержимое $VARIABLE будет напечатано три раза.  for VARIABLE in {1..3}  do      echo "$VARIABLE"  done +# => 1 +# => 2 +# => 3 + -# Или с использованием "традиционного" синтаксиса цикла for: +# Или с использованием «традиционного» синтаксиса цикла for:  for ((a=1; a <= 3; a++))  do      echo $a  done +# => 1 +# => 2 +# => 3  # Цикл for можно использовать для действий с файлами. -# Запустим команду 'cat' для файлов file1 и file2 +# Запустим команду «cat» для файлов file1 и file2  for VARIABLE in file1 file2  do      cat "$VARIABLE" @@ -221,52 +374,89 @@ done  # Цикл while:  while [ true ]  do -    echo "тело цикла здесь..." +    echo "Здесь тело цикла..."      break  done +# => Здесь тело цикла... -# Вы можете определять функции +# Вы также можете определять функции  # Определение:  function foo ()  { -    echo "Аргументы работают также, как аргументы скрипта: $@" -    echo "и: $1 $2..." +    echo "Аргументы работают так же, как и аргументы скрипта: $@" +    echo "И так: $1 $2..."      echo "Это функция"      return 0  } +# Вызовем функцию `foo` с двумя аргументами, arg1 и arg2: +foo arg1 arg2 +# => Аргументы работают так же, как и аргументы скрипта: arg1 arg2 +# => И так: arg1 arg2... +# => Это функция  # или просто  bar ()  { -    echo "Другой способ определить функцию!" +    echo "Другой способ определять функции!"      return 0  } +# Вызовем функцию `bar` без аргументов: +bar # => Другой способ определять функции!  # Вызов функции -foo "Мое имя" $NAME +foo "Меня зовут" $NAME  # Есть много полезных команд, которые нужно знать:  # напечатать последние 10 строк файла file.txt  tail -n 10 file.txt +  # напечатать первые 10 строк файла file.txt  head -n 10 file.txt +  # отсортировать строки file.txt  sort file.txt -# отобрать или наоборот пропустить повторяющиеся строки (с опцией -d отбирает) + +# отобрать или наоборот пропустить повторяющиеся строки (с параметром `-d` отбирает строки)  uniq -d file.txt -# напечатать только первую колонку перед символом ',' + +# напечатать только первый столбец перед символом «,»  cut -d ',' -f 1 file.txt -# заменить каждое 'okay' на 'great' в файле file.txt (regex поддерживается) -sed -i 's/okay/great/g' file.txt -# вывести в stdout все строки из file.txt, совпадающие с шаблоном regex; -# этот пример выводит строки, которые начинаются на "foo" и оканчиваются "bar" + +# заменить каждое вхождение «хорошо» на «прекрасно» в файле file.txt +# (поддерживаются регулярные выражения) +sed -i 's/хорошо/прекрасно/g' file.txt + +# вывести в stdout все строки из file.txt, соответствующие регулярному выражению +# этот пример выводит строки, которые начинаются на «foo» и оканчиваются на «bar»  grep "^foo.*bar$" file.txt -# передайте опцию -c чтобы вывести число строк, в которых совпал шаблон + +# Передайте параметр `-c`, чтобы вывести лишь число строк, +# соответствующих регулярному выражению  grep -c "^foo.*bar$" file.txt -# чтобы искать по строке, а не шаблону regex, используйте fgrep (или grep -F) + +# Ниже приведены другие полезные параметры: +grep -r "^foo.*bar$" someDir/ # рекурсивный `grep` +grep -n "^foo.*bar$" file.txt # задаются номера строк +grep -rI "^foo.*bar$" someDir/ # рекурсивный `grep` с игнорированием двоичных файлов + +# Выполнить тот же изначальный поиск, но удалив строки, содержащие «baz» +grep "^foo.*bar$" file.txt | grep -v "baz" + +# чтобы искать непосредственно по строке, а не в соответствии  +# с регулярным выражением, используйте fgrep (или grep -F):  fgrep "^foo.*bar$" file.txt  -# Читайте встроенную документацию оболочки Bash командой 'help': +# Команда `trap` позволяет выполнить некую команду, когда ваш скрипт +# принимает определённый Posix-сигнал. В следующем примере `trap` выполнит `rm`, +# если скрипт примет один из трёх перечисленных сигналов. +trap "rm $TEMP_FILE; exit" SIGHUP SIGINT SIGTERM + +# `sudo` используется для выполнения команд с правами суперпользователя +NAME1=$(whoami) +NAME2=$(sudo whoami) +echo "Был $NAME1, затем стал более мощным $NAME2" + +# Читайте встроенную документацию оболочки Bash командой `help`:  help  help help  help for @@ -274,18 +464,18 @@ help return  help source  help . -# Читайте Bash man-документацию +# Читайте man-документацию Bash командой `man`:  apropos bash  man 1 bash  man bash -# Читайте документацию info (? для помощи) +# Читайте документацию info (? для справки)  apropos info | grep '^info.*('  man info  info info  info 5 info -# Читайте bash info документацию: +# Читайте info-документацию Bash:  info bash  info bash 'Bash Features'  info bash 6 diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown index b9704fc3..35994749 100644 --- a/ru-ru/c++-ru.html.markdown +++ b/ru-ru/c++-ru.html.markdown @@ -886,7 +886,6 @@ v.swap(vector<Foo>());  ```  ## Дальнейшее чтение: -Наиболее полное и обновленное руководство по С++ можно найти на -<http://cppreference.com/w/cpp> - -Дополнительные ресурсы могут быть найдены на <http://cplusplus.com> +* Наиболее полное и обновленное руководство по С++ можно найти на [CPP Reference](http://cppreference.com/w/cpp). +* Дополнительные ресурсы могут быть найдены на [CPlusPlus](http://cplusplus.com). +* Учебник, посвященный основам языка и настройке среды кодирования, доступен в [TheChernoProject - C ++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb). diff --git a/ru-ru/clojure-ru.html.markdown b/ru-ru/clojure-ru.html.markdown index 356d1cc0..19233d23 100644 --- a/ru-ru/clojure-ru.html.markdown +++ b/ru-ru/clojure-ru.html.markdown @@ -8,9 +8,9 @@ translators:  lang: ru-ru  --- -Clojure, это представитель семейства Lisp-подобных языков, разработанный +Clojure — это представитель семейства Lisp-подобных языков, разработанный  для Java Virtual Machine. Язык идейно гораздо ближе к чистому -[функциональному программированию](https://ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5) чем его прародитель Common Lisp, но в то же время обладает набором инструментов для работы с состоянием, +[функциональному программированию](https://ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5), чем его прародитель Common Lisp, но в то же время обладает набором инструментов для работы с состоянием,  таких как [STM](https://ru.wikipedia.org/wiki/Software_transactional_memory).  Благодаря такому сочетанию технологий в одном языке, разработка программ, @@ -23,9 +23,9 @@ Clojure, это представитель семейства Lisp-подобн  ```clojure  ; Комментарии начинаются символом ";". -; Код на языке Clojure записывается в виде "форм", +; Код на языке Clojure записывается в виде «форм»,  ; которые представляют собой обычные списки элементов, разделенных пробелами, -; заключённые в круглые скобки +; заключённые в круглые скобки.  ;  ; Clojure Reader (инструмент языка, отвечающий за чтение исходного кода),  ; анализируя форму, предполагает, что первым элементом формы (т.е. списка) @@ -76,32 +76,32 @@ Clojure, это представитель семейства Lisp-подобн  '(+ 1 2) ; => (+ 1 2)  ; ("'", это краткая запись формы (quote (+ 1 2)) -; "Квотированный" список можно вычислить, передав его функции eval +; «Квотированный» список можно вычислить, передав его функции eval  (eval '(+ 1 2)) ; => 3  ; Коллекции и Последовательности  ;;;;;;;;;;;;;;;;;;; -; Списки (Lists) в clojure структурно представляют собой "связанные списки", +; Списки (Lists) в clojure структурно представляют собой «связанные списки»,  ; тогда как Векторы (Vectors), устроены как массивы.  ; Векторы и Списки тоже являются классами Java!  (class [1 2 3]); => clojure.lang.PersistentVector  (class '(1 2 3)); => clojure.lang.PersistentList -; Список может быть записан, как (1 2 3), но в этом случае +; Список может быть записан как (1 2 3), но в этом случае  ; он будет воспринят reader`ом, как вызов функции.  ; Есть два способа этого избежать:  ; '(1 2 3)     - квотирование,  ; (list 1 2 3) - явное конструирование списка с помощью функции list. -; "Коллекции", это некие наборы данных +; «Коллекции» — это некие наборы данных.  ; И списки, и векторы являются коллекциями:  (coll? '(1 2 3)) ; => true  (coll? [1 2 3]) ; => true -; "Последовательности" (seqs), это абстракция над наборами данных, +; «Последовательности» (seqs) — это абстракция над наборами данных,  ; элементы которых "упакованы" последовательно. -; Списки - последовательности, а вектора - нет. +; Списки — последовательности, а векторы — нет.  (seq? '(1 2 3)) ; => true  (seq? [1 2 3]) ; => false @@ -119,7 +119,7 @@ Clojure, это представитель семейства Lisp-подобн  ; Функция conj добавляет элемент в коллекцию  ; максимально эффективным для неё способом. -; Для списков эффективно добавление в начло, а для векторов - в конец. +; Для списков эффективно добавление в начло, а для векторов — в конец.  (conj [1 2 3] 4) ; => [1 2 3 4]  (conj '(1 2 3) 4) ; => (4 1 2 3) @@ -130,7 +130,7 @@ Clojure, это представитель семейства Lisp-подобн  (map inc [1 2 3]) ; => (2 3 4)  (filter even? [1 2 3]) ; => (2) -; reduce поможет "свернуть" коллекцию +; reduce поможет «свернуть» коллекцию  (reduce + [1 2 3 4])  ; = (+ (+ (+ 1 2) 3) 4)  ; => 10 @@ -144,12 +144,12 @@ Clojure, это представитель семейства Lisp-подобн  ;;;;;;;;;;;;;;;;;;;;;  ; Функция создается специальной формой fn. -; "Тело" функции может состоять из нескольких форм, +; «Тело» функции может состоять из нескольких форм,  ; но результатом вызова функции всегда будет результат вычисления  ; последней из них.  (fn [] "Hello World") ; => fn -; (Вызов функции требует "оборачивания" fn-формы в форму вызова) +; (Вызов функции требует «оборачивания» fn-формы в форму вызова)  ((fn [] "Hello World")) ; => "Hello World"  ; Назначить значению имя можно специальной формой def @@ -160,7 +160,7 @@ x ; => 1  (def hello-world (fn [] "Hello World"))  (hello-world) ; => "Hello World" -; Поскольку именование функций - очень частая операция, +; Поскольку именование функций — очень частая операция,  ; clojure позволяет, сделать это проще:  (defn hello-world [] "Hello World") @@ -211,7 +211,7 @@ x ; => 1  ; Отображения могут использовать в качестве ключей любые хэшируемые значения,  ; однако предпочтительными являются ключи, -; являющиеся "ключевыми словами" (keywords) +; являющиеся «ключевыми словами» (keywords)  (class :a) ; => clojure.lang.Keyword  (def stringmap {"a" 1, "b" 2, "c" 3}) @@ -263,7 +263,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут  ; Исключаются - посредством disj  (disj #{1 2 3} 1) ; => #{2 3} -; Вызов множества, как функции, позволяет проверить +; Вызов множества как функции позволяет проверить  ; принадлежность элемента этому множеству:  (#{1 2 3} 1) ; => 1  (#{1 2 3} 4) ; => nil @@ -274,8 +274,8 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут  ; Полезные формы  ;;;;;;;;;;;;;;;;; -; Конструкции ветвления в clojure, это обычные макросы -; и подобны их собратьям в других языках: +; Конструкции ветвления в clojure — это обычные макросы, +; они подобны своим собратьям в других языках:  (if false "a" "b") ; => "b"  (if false "a") ; => nil @@ -285,7 +285,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут  (let [a 1 b 2]    (> a b)) ; => false -; Несколько форм можно объединить в одну форму посредством do +; Несколько форм можно объединить в одну форму посредством do.  ; Значением do-формы будет значение последней формы из списка вложенных в неё:  (do    (print "Hello") @@ -298,7 +298,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут    (str "Hello " name))  (print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") -; Ещё один пример - let: +; Ещё один пример — let:  (let [name "Urkel"]    (print "Saying hello to " name)    (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") @@ -306,7 +306,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут  ; Модули  ;;;;;;;;; -; Форма "use" позволяет добавить в текущее пространство имен +; Форма use позволяет добавить в текущее пространство имен  ; все имена (вместе со значениями) из указанного модуля:  (use 'clojure.set) @@ -392,7 +392,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут  my-atom  ;=> Atom<#...> (Возвращает объект типа Atom)  @my-atom ; => {:a 1 :b 2} -; Пример реализации счётчика на атоме +; Пример реализации счётчика на атоме:  (def counter (atom 0))  (defn inc-counter []    (swap! counter inc)) @@ -414,13 +414,13 @@ my-atom  ;=> Atom<#...> (Возвращает объект типа Atom)  Это руководство не претендует на полноту, но мы смеем надеяться, способно вызвать интерес к дальнейшему изучению языка. -Clojure.org - сайт содержит большое количество статей по языку: +Сайт Clojure.org содержит большое количество статей по языку:  [http://clojure.org/](http://clojure.org/) -Clojuredocs.org - сайт документации языка с примерами использования функций: +Clojuredocs.org — сайт документации языка с примерами использования функций:  [http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) -4Clojure - отличный способ закрепить навыки программирования на clojure, решая задачи вместе с коллегами со всего мира: +4Clojure — отличный способ закрепить навыки программирования на clojure, решая задачи вместе с коллегами со всего мира:  [http://www.4clojure.com/](http://www.4clojure.com/)  Clojure-doc.org (да, именно) неплохой перечень статей для начинающих: diff --git a/ru-ru/common-lisp-ru.html.markdown b/ru-ru/common-lisp-ru.html.markdown new file mode 100644 index 00000000..d5f9bf0e --- /dev/null +++ b/ru-ru/common-lisp-ru.html.markdown @@ -0,0 +1,704 @@ +--- + +language: "Common Lisp" +filename: commonlisp.lisp +contributors: +  - ["Paul Nathan", "https://github.com/pnathan"] +  - ["Rommel Martinez", "https://ebzzry.io"] +translators: +  - ["Michael Filonenko", "https://github.com/filonenko-mikhail"] +lang: ru-ru +--- + +Common Lisp - мультипарадигменный язык программирования общего назначения, подходящий для широкого +спектра задач. +Его частенько называют программируемым языком программирования. + +Идеальная отправная точка - книга [Common Lisp на практике (перевод)](http://lisper.ru/pcl/). +Ещё одна популярная книга [Land of Lisp](http://landoflisp.com/). +И одна из последних книг [Common Lisp Recipes](http://weitz.de/cl-recipes/) вобрала в себя лучшие +архитектурные решения на основе опыта коммерческой работки автора. + + + +```common-lisp + +;;;----------------------------------------------------------------------------- +;;; 0. Синтаксис +;;;----------------------------------------------------------------------------- + +;;; Основные формы + +;;; Существует два фундамента CL: АТОМ и S-выражение. +;;; Как правило, сгруппированные S-выражения называют `формами`. + +10            ; атом; вычисляется в самого себя +:thing        ; другой атом; вычисляется в символ :thing +t             ; ещё один атом, обозначает `истину` (true) +(+ 1 2 3 4)   ; s-выражение +'(4 :foo t)   ; ещё одно s-выражение + +;;; Комментарии + +;;; Однострочные комментарии начинаются точкой с запятой. Четыре знака подряд +;;; используют для комментария всего файла, три для раздела, два для текущего +;;; определения; один для текущей строки. Например: + +;;;; life.lisp + +;;; То-сё - пятое-десятое. Оптимизировано для максимального бадабума и ччччч. +;;; Требуется для функции PoschitatBenzinIsRossiiVBelarus + +(defun meaning (life) +  "Возвращает смысл Жизни" +  (let ((meh "abc")) +    ;; Вызывает бадабум +    (loop :for x :across meh +       :collect x)))                    ; сохранить значения в x, и потом вернуть + +;;; А вот целый блок комментария можно использовать как угодно. +;;; Для него используются #| и |# + +#| Целый блок комментария, который размазан +   на несколько строк +    #| +       которые могут быть вложенными! +    |# +|# + +;;; Чем пользоваться + +;;; Существует несколько реализаций: и коммерческих, и открытых. +;;; Все они максимально соответствуют стандарту языка. +;;; SBCL, например, добротен. А за дополнительными библиотеками +;;; нужно ходить в Quicklisp + +;;; Обычно разработка ведется в текстовом редакторе с запущенным в цикле +;;; интерпретатором (в CL это Read Eval Print Loop). Этот цикл (REPL) +;;; позволяет интерактивно выполнять части программы вживую сразу наблюдая +;;; результат. + +;;;----------------------------------------------------------------------------- +;;; 1. Базовые типы и операторы +;;;----------------------------------------------------------------------------- + +;;; Символы + +'foo ; => FOO Символы автоматически приводятся к верхнему регистру. + +;;; INTERN создаёт символ из строки. + +(intern "AAAA")        ; => AAAA +(intern "aaa")         ; => |aaa| + +;;; Числа + +9999999999999999999999 ; целые +#b111                  ; двоичные => 7 +#o111                  ; восьмеричные => 73 +#x111                  ; шестнадцатиричные => 273 +3.14159s0              ; с плавающей точкой +3.14159d0              ; с плавающей точкой с двойной точностью +1/2                    ; рациональные) +#C(1 2)                ; комплексные + +;;; Вызов функции пишется как s-выражение (f x y z ....), где f это функция, +;;; x, y, z, ... аругменты. + +(+ 1 2)                ; => 3 + +;;; Если вы хотите просто представить код как данные, воспользуйтесь формой QUOTE +;;; Она не вычисляет аргументы, а возвращает их как есть. +;;; Она даёт начало метапрограммированию + +(quote (+ 1 2))        ; => (+ 1 2) +(quote a)              ; => A + +;;; QUOTE можно сокращенно записать знаком ' + +'(+ 1 2)               ; => (+ 1 2) +'a                     ; => A + +;;; Арифметические операции + +(+ 1 1)                ; => 2 +(- 8 1)                ; => 7 +(* 10 2)               ; => 20 +(expt 2 3)             ; => 8 +(mod 5 2)              ; => 1 +(/ 35 5)               ; => 7 +(/ 1 3)                ; => 1/3 +(+ #C(1 2) #C(6 -4))   ; => #C(7 -2) + +;;; Булевые + +t                      ; истина; любое не-NIL значение `истинно` +nil                    ; ложь; а ещё пустой список () тоже `ложь` +(not nil)              ; => T +(and 0 t)              ; => T +(or 0 nil)             ; => 0 + +;;; Строковые символы + +#\A                    ; => #\A +#\λ                    ; => #\GREEK_SMALL_LETTER_LAMDA +#\u03BB                ; => #\GREEK_SMALL_LETTER_LAMDA + +;;; Строки это фиксированные массивы символов + +"Hello, world!" +"Тимур \"Каштан\" Бадтрудинов"   ; экранировать двойную кавычку обратным слешом + +;;; Строки можно соединять + +(concatenate 'string "ПРивет, " "мир!") ; => "ПРивет, мир!" + +;;; Можно пройтись по строке как по массиву символов + +(elt "Apple" 0) ; => #\A + +;;; Для форматированного вывода используется FORMAT. Он умеет выводить, как просто значения, +;;; так и производить циклы и учитывать условия. Первый агрумент указывает куда отправить +;;; результат. Если NIL, FORMAT вернет результат как строку, если T результат отправиться +;;; консоль вывода а форма вернет NIL. + +(format nil "~A, ~A!" "Привет" "мир")   ; => "Привет, мир!" +(format t "~A, ~A!" "Привет" "мир")     ; => NIL + + +;;;----------------------------------------------------------------------------- +;;; 2. Переменные +;;;----------------------------------------------------------------------------- + +;;; С помощью DEFVAR и DEFPARAMETER вы можете создать глобальную (динамческой видимости) +;;; переменную. +;;; Имя переменной может состоять из любых символов кроме: ()",'`;#|\ + +;;; Разница между DEFVAR и DEFPARAMETER в том, что повторное выполнение DEFVAR +;;; переменную не поменяет. А вот DEFPARAMETER меняет переменную при каждом вызове. + +;;; Обычно глобальные (динамически видимые) переменные содержат звездочки в имени. + +(defparameter *some-var* 5) +*some-var* ; => 5 + +;;; Можете использовать unicode. +(defparameter *КУКУ* nil) + +;;; Доступ к необъявленной переменной - это непредсказуемое поведение. Не делайте так. + +;;; С помощью LET можете сделать локальное связывание. +;;; В следующем куске кода, `я` связывается с "танцую с тобой" только +;;; внутри формы (let ...). LET всегда возвращает значение последней формы. + +(let ((я "танцую с тобой")) я) ; => "танцую с тобой" + + +;;;-----------------------------------------------------------------------------; +;;; 3. Структуры и коллекции +;;;-----------------------------------------------------------------------------; + + +;;; Структуры + +(defstruct dog name breed age) +(defparameter *rover* +    (make-dog :name "rover" +              :breed "collie" +              :age 5)) +*rover*            ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5) +(dog-p *rover*)    ; => T +(dog-name *rover*) ; => "rover" + +;;; DEFSTRUCT автоматически создала DOG-P, MAKE-DOG, и DOG-NAME + + +;;; Пары (cons-ячейки) + +;;; CONS создаёт пары. CAR и CDR возвращают начало и конец CONS-пары. + +(cons 'SUBJECT 'VERB)         ; => '(SUBJECT . VERB) +(car (cons 'SUBJECT 'VERB))   ; => SUBJECT +(cdr (cons 'SUBJECT 'VERB))   ; => VERB + + +;;; Списки + +;;; Списки это связанные CONS-пары, в конце самой последней из которых стоит NIL +;;; (или '() ). + +(cons 1 (cons 2 (cons 3 nil)))     ; => '(1 2 3) + +;;; Списки с произвольным количеством элементов удобно создавать с помощью LIST + +(list 1 2 3)                       ; => '(1 2 3) + +;;; Если первый аргумент для CONS это атом и второй аргумент список, CONS +;;; возвращает новую CONS-пару, которая представляет собой список + +(cons 4 '(1 2 3))                  ; => '(4 1 2 3) + +;;; Чтобы объединить списки, используйте APPEND + +(append '(1 2) '(3 4))             ; => '(1 2 3 4) + +;;; Или CONCATENATE + +(concatenate 'list '(1 2) '(3 4))  ; => '(1 2 3 4) + +;;; Списки это самый используемый элемент языка. Поэтому с ними можно делать +;;; многие вещи. Вот несколько примеров: + +(mapcar #'1+ '(1 2 3))             ; => '(2 3 4) +(mapcar #'+ '(1 2 3) '(10 20 30))  ; => '(11 22 33) +(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4) +(every #'evenp '(1 2 3 4))         ; => NIL +(some #'oddp '(1 2 3 4))           ; => T +(butlast '(subject verb object))   ; => (SUBJECT VERB) + + +;;; Вектора + +;;; Вектора заданные прямо в коде - это массивы с фиксированной длинной. + +#(1 2 3) ; => #(1 2 3) + +;;; Для соединения векторов используйте CONCATENATE + +(concatenate 'vector #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + + +;;; Массивы + +;;; И вектора и строки это подмножества массивов. + +;;; Двухмерные массивы + +(make-array (list 2 2))         ; => #2A((0 0) (0 0)) +(make-array '(2 2))             ; => #2A((0 0) (0 0)) +(make-array (list 2 2 2))       ; => #3A(((0 0) (0 0)) ((0 0) (0 0))) + +;;; Внимание: значение по-умолчанию элемента массива зависит от реализации. +;;; Лучше явно указывайте: + +(make-array '(2) :initial-element 'unset)  ; => #(UNSET UNSET) + +;;; Для доступа к элементу в позиции 1, 1, 1: + +(aref (make-array (list 2 2 2)) 1 1 1)     ;  => 0 + + +;;; Вектора с изменяемой длиной + +;;; Вектора с изменяемой длиной при выводе на консоль выглядят также, +;;; как и вектора, с константной длиной + +(defparameter *adjvec* (make-array '(3) :initial-contents '(1 2 3) +                                   :adjustable t :fill-pointer t)) +*adjvec* ; => #(1 2 3) + +;;; Добавление новых элементов + +(vector-push-extend 4 *adjvec*)   ; => 3 +*adjvec*                          ; => #(1 2 3 4) + + +;;; Множества, это просто списки: + +(set-difference '(1 2 3 4) '(4 5 6 7))   ; => (3 2 1) +(intersection '(1 2 3 4) '(4 5 6 7))     ; => 4 +(union '(1 2 3 4) '(4 5 6 7))            ; => (3 2 1 4 5 6 7) +(adjoin 4 '(1 2 3 4))                    ; => (1 2 3 4) + +;;; Несмотря на все, для действительно больших объемов данных, вам нужно что-то +;;; лучше, чем просто связанные списки + +;;; Словари представлены хеш таблицами. + +;;; Создание хеш таблицы: + +(defparameter *m* (make-hash-table)) + +;;; Установка пары ключ-значение + +(setf (gethash 'a *m*) 1) + +;;; Возврат значения по ключу + +(gethash 'a *m*) ; => 1, T + +;;; CL выражения умеют возвращать сразу несколько значений. + +(values 1 2) ; => 1, 2 + +;;; которые могут быть распределены по переменным с помощью MULTIPLE-VALUE-BIND + +(multiple-value-bind (x y) +    (values 1 2) +  (list y x)) + +; => '(2 1) + +;;; GETHASH как раз та функция, которая возвращает несколько значений. Первое +;;; значение - это значение по ключу в хеш таблицу. Если ключ не был найден, +;;; возвращает NIL. + +;;; Второе возвращаемое значение, указывает был ли ключ в хеш таблице. Если ключа +;;; не было, то возвращает NIL. Таким образом можно проверить, это значение +;;; NIL, или ключа просто не было. + +;;; Вот возврат значений, в случае когда ключа в хеш таблице не было: + +(gethash 'd *m*) ;=> NIL, NIL + +;;; Можете задать значение по умолчанию. + +(gethash 'd *m* :not-found) ; => :NOT-FOUND + +;;; Давайте обработаем возврат несколько значений. + +(multiple-value-bind (a b) +    (gethash 'd *m*) +  (list a b)) +; => (NIL NIL) + +(multiple-value-bind (a b) +    (gethash 'a *m*) +  (list a b)) +; => (1 T) + + +;;;----------------------------------------------------------------------------- +;;; 3. Функции +;;;----------------------------------------------------------------------------- + +;;; Для создания анонимных функций используйте LAMBDA. Функций всегда возвращают +;;; значение последнего своего выражения. Как выглядит функция при выводе в консоль +;;; зависит от реализации. + +(lambda () "Привет Мир") ; => #<FUNCTION (LAMBDA ()) {1004E7818B}> + +;;; Для вызова анонимной функции пользуйтесь FUNCALL + +(funcall (lambda () "Привет Мир"))   ; => "Привет мир" +(funcall #'+ 1 2 3)                   ; => 6 + +;;; FUNCALL сработает и тогда, когда анонимная функция стоит в начале +;;; неэкранированного списка + +((lambda () "Привет Мир"))           ; => "Привет Мир" +((lambda (val) val) "Привет Мир")    ; => "Привет Мир" + +;;; FUNCALL используется, когда аргументы заранее известны. +;;; В противном случае используйте APPLY + +(apply #'+ '(1 2 3))   ; => 6 +(apply (lambda () "Привет Мир") nil) ; => "Привет Мир" + +;;; Для обычной функции с именем используйте DEFUN + +(defun hello-world () "Привет Мир") +(hello-world) ; => "Привет Мир" + +;;; Выше видно пустой список (), это место для определения аргументов + +(defun hello (name) (format nil "Hello, ~A" name)) +(hello "Григорий") ; => "Привет, Григорий" + +;;; Можно указать необязательные аргументы. По умолчанию они будут NIL + +(defun hello (name &optional from) +  (if from +      (format t "Приветствие для ~A от ~A" name from) +      (format t "Привет, ~A" name))) + +(hello "Георгия" "Василия")       ; => Приветствие для Георгия от Василия + +;;; Можно явно задать значения по умолчанию + +(defun hello (name &optional (from "Мира")) +   (format nil "Приветствие для ~A от ~A" name from)) + +(hello "Жоры")               ; => Приветствие для Жоры от Мира +(hello "Жоры" "альпаки")     ; => Приветствие для Жоры от альпаки + +;;; Можно также задать именованные параметры + +(defun generalized-greeter (name &key (from "Мира") (honorific "Господин")) +  (format t "Здравствуйте, ~A ~A, от ~A" honorific name from)) + +(generalized-greeter "Григорий") +; => Здравствуйте, Господин Григорий, от Мира + +(generalized-greeter "Григорий" :from "альпаки" :honorific "гражданин") +; => Здравствуйте, Гражданин Григорий, от альпаки + + +;;;----------------------------------------------------------------------------- +;;; 4. Равенство или эквивалентность +;;;----------------------------------------------------------------------------- + +;;; У CL сложная система эквивалентности. Взглянем одним глазом. + +;;; Для чисел используйте `=' +(= 3 3.0)               ; => T +(= 2 1)                 ; => NIL + +;;; Для идентичености объектов используйте EQL +(eql 3 3)               ; => T +(eql 3 3.0)             ; => NIL +(eql (list 3) (list 3)) ; => NIL + +;;; Для списков, строк, и битовых векторов - EQUAL +(equal (list 'a 'b) (list 'a 'b)) ; => T +(equal (list 'a 'b) (list 'b 'a)) ; => NIL + + +;;;----------------------------------------------------------------------------- +;;; 5. Циклы и ветвления +;;;----------------------------------------------------------------------------- + +;;; Ветвления + +(if t                    ; проверямое значение +    "случилась истина"   ; если, оно было истинно +    "случилась ложь")    ; иначе, когда оно было ложно +; => "случилась истина" + +;;; В форме ветвления if, все не-NIL значения это `истина` + +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) +(if (member 'Groucho '(Harpo Groucho Zeppo)) +    'yep +    'nope) +; => 'YEP + +;;; COND это цепочка проверок для нахождения искомого +(cond ((> 2 2) (error "мимо!")) +      ((< 2 2) (error "опять мимо!")) +      (t 'ok)) ; => 'OK + +;;; TYPECASE выбирает ветку исходя из типа выражения +(typecase 1 +  (string :string) +  (integer :int)) +; => :int + + +;;; Циклы + +;;; С рекурсией + +(defun fact (n) +  (if (< n 2) +      1 +    (* n (fact(- n 1))))) + +(fact 5) ; => 120 + +;;; И без + +(defun fact (n) +  (loop :for result = 1 :then (* result i) +     :for i :from 2 :to n +     :finally (return result))) + +(fact 5) ; => 120 + +(loop :for x :across "abc" :collect x) +; => (#\a #\b #\c #\d) + +(dolist (i '(1 2 3 4)) +  (format t "~A" i)) +; => 1234 + + +;;;----------------------------------------------------------------------------- +;;; 6. Установка значений в переменные (и не только) +;;;----------------------------------------------------------------------------- + +;;; Для присвоения переменной нового значения используйте SETF. Это уже было +;;; при работе с хеш таблицами. + +(let ((variable 10)) +    (setf variable 2)) +; => 2 + +;;; Для функционального подхода в программировании, старайтесь избегать измений +;;; в переменных. + +;;;----------------------------------------------------------------------------- +;;; 7. Классы и объекты +;;;----------------------------------------------------------------------------- + +;;; Никаких больше животных в примерах. Берем устройства приводимые в движение +;;; мускульной силой человека. + +(defclass human-powered-conveyance () +  ((velocity +    :accessor velocity +    :initarg :velocity) +   (average-efficiency +    :accessor average-efficiency +   :initarg :average-efficiency)) +  (:documentation "Устройство движимое человеческой силой")) + +;;; Аргументы DEFCLASS: +;;; 1. Имя класса +;;; 2. Список родительских классов +;;; 3. Список полей +;;; 4. Необязательная метаинформация + +;;; Если родительские классы не заданы, используется "стандартный" класс +;;; Это можно *изменить*, но хорошенько подумайте прежде. Если все-таки +;;; решились вам поможет "Art of the Metaobject Protocol" + +(defclass bicycle (human-powered-conveyance) +  ((wheel-size +    :accessor wheel-size +    :initarg :wheel-size +    :documentation "Diameter of the wheel.") +   (height +    :accessor height +    :initarg :height))) + +(defclass recumbent (bicycle) +  ((chain-type +    :accessor chain-type +    :initarg :chain-type))) + +(defclass unicycle (human-powered-conveyance) nil) + +(defclass canoe (human-powered-conveyance) +  ((number-of-rowers +    :accessor number-of-rowers +    :initarg :number-of-rowers))) + +;;; Если вызвать DESCRIBE для HUMAN-POWERED-CONVEYANCE то получите следующее: + +(describe 'human-powered-conveyance) + +; COMMON-LISP-USER::HUMAN-POWERED-CONVEYANCE +;  [symbol] +; +; HUMAN-POWERED-CONVEYANCE names the standard-class #<STANDARD-CLASS +;                                                    HUMAN-POWERED-CONVEYANCE>: +;  Documentation: +;    A human powered conveyance +;  Direct superclasses: STANDARD-OBJECT +;  Direct subclasses: UNICYCLE, BICYCLE, CANOE +;  Not yet finalized. +;  Direct slots: +;    VELOCITY +;      Readers: VELOCITY +;      Writers: (SETF VELOCITY) +;    AVERAGE-EFFICIENCY +;      Readers: AVERAGE-EFFICIENCY +;      Writers: (SETF AVERAGE-EFFICIENCY) + +;;; CL задизайнен как интерактивная система. В рантайме доступна информация о +;;; типе объектов. + +;;; Давайте посчитаем расстояние, которое пройдет велосипед за один оборот колеса +;;; по формуле C = d * pi + +(defmethod circumference ((object bicycle)) +  (* pi (wheel-size object))) + +;;; PI - это константа в CL + +;;; Предположим мы нашли, что критерий эффективности логарифмически связан +;;; с гребцами каноэ. Тогда вычисление можем сделать сразу при инициализации. + +;;; Инициализируем объект после его создания: + +(defmethod initialize-instance :after ((object canoe) &rest args) +  (setf (average-efficiency object)  (log (1+ (number-of-rowers object))))) + + +;;; Давайте проверим что получилось с этой самой эффективностью... + +(average-efficiency (make-instance 'canoe :number-of-rowers 15)) +; => 2.7725887 + + +;;;----------------------------------------------------------------------------- +;;; 8. Макросы +;;;----------------------------------------------------------------------------- + +;;; Макросы позволяют расширить синаксис языка. В CL нет например цикла WHILE, +;;; но его проще простого реализовать на макросах. Если мы отбросим наши +;;; ассемблерные (или алгольные) инстинкты, мы взлетим на крыльях: + +(defmacro while (condition &body body) +    "Пока `условие` истинно, выполняется `тело`. +`Условие` проверяется перед каждым выполнением `тела`" +    (let ((block-name (gensym)) (done (gensym))) +        `(tagbody +           ,block-name +           (unless ,condition +               (go ,done)) +           (progn +           ,@body) +           (go ,block-name) +           ,done))) + +;;; Взглянем на более высокоуровневую версию этого макроса: + +(defmacro while (condition &body body) +    "Пока `условие` истинно, выполняется `тело`. +`Условие` проверяется перед каждым выполнением `тела`" +  `(loop while ,condition +         do +         (progn +            ,@body))) + +;;; В современных комиляторах LOOP так же эффективен как и приведенный +;;; выше код. Поэтому используйте его, его проще читать. + +;;; В макросах используются символы ```, `,` и `@`. ``` - это оператор +;;; квазиквотирования - это значит что форма исполнятся не будет, а вернется +;;; как данные. Оператаор `,` позволяет исполнить форму внутри +;;; квазиквотирования. Оператор `@` исполняет форму внутри квазиквотирования +;;; но полученный список вклеивает по месту. + +;;; GENSYM создаёт уникальный символ, который гарантировано больше нигде в +;;; системе не используется. Так надо потому, что макросы разворачиваются +;;; во время компиляции и переменные объявленные в макросе могут совпасть +;;; по имени с переменными в обычном коде. + +;;; Дальнйешую информацию о макросах ищите в книгах Practical Common Lisp +;;; и On Lisp +``` + +## Для чтения + +На русском +- [Practical Common Lisp](http://www.gigamonkeys.com/book/) + +На английском +- [Practical Common Lisp](http://www.gigamonkeys.com/book/) +- [Common Lisp: A Gentle Introduction to Symbolic Computation](https://www.cs.cmu.edu/~dst/LispBook/book.pdf) + + +## Дополнительная информация + +На русском + +- [Lisper.ru](http://lisper.ru/) + +На английском + +- [CLiki](http://www.cliki.net/) +- [common-lisp.net](https://common-lisp.net/) +- [Awesome Common Lisp](https://github.com/CodyReichert/awesome-cl) +- [Lisp Lang](http://lisp-lang.org/) + + +## Благодарности в английской версии + +Спасибо людям из Scheme за отличную статью, взятую за основу для +Common Lisp. + + +- [Paul Khuong](https://github.com/pkhuong) за хорошую вычитку. diff --git a/ru-ru/crystal-ru.html.markdown b/ru-ru/crystal-ru.html.markdown new file mode 100644 index 00000000..87d12f23 --- /dev/null +++ b/ru-ru/crystal-ru.html.markdown @@ -0,0 +1,584 @@ +--- +language: crystal +filename: learncrystal-ru.cr +contributors: +    - ["Vitalii Elenhaupt", "http://veelenga.com"] +    - ["Arnaud Fernandés", "https://github.com/TechMagister/"] +translators: +    - ["Den Patin", "https://github.com/denpatin"] +lang: ru-ru +--- + +```crystal +# — так начинается комментарий + + +# Всё является объектом +nil.class  #=> Nil +100.class  #=> Int32 +true.class #=> Bool + +# Возвращают false только nil, false и пустые указатели +!nil   #=> true  : Bool +!false #=> true  : Bool +!0     #=> false : Bool + + +# Целые числа + +1.class #=> Int32 + +# Четыре типа целых чисел со знаком +1_i8.class  #=> Int8 +1_i16.class #=> Int16 +1_i32.class #=> Int32 +1_i64.class #=> Int64 + +# Четыре типа целых чисел без знака +1_u8.class  #=> UInt8 +1_u16.class #=> UInt16 +1_u32.class #=> UInt32 +1_u64.class #=> UInt64 + +2147483648.class          #=> Int64 +9223372036854775808.class #=> UInt64 + +# Двоичные числа +0b1101 #=> 13 : Int32 + +# Восьмеричные числа +0o123 #=> 83 : Int32 + +# Шестнадцатеричные числа +0xFE012D #=> 16646445 : Int32 +0xfe012d #=> 16646445 : Int32 + +# Числа с плавающей точкой + +1.0.class #=> Float64 + +# Два типа чисел с плавающей запятой +1.0_f32.class #=> Float32 +1_f32.class   #=> Float32 + +1e10.class    #=> Float64 +1.5e10.class  #=> Float64 +1.5e-7.class  #=> Float64 + + +# Символьные литералы + +'a'.class #=> Char + +# Восьмеричный код символа +'\101' #=> 'A' : Char + +# Код символа Unicode +'\u0041' #=> 'A' : Char + + +# Строки + +"s".class #=> String + +# Строки неизменяемы +s = "hello, "  #=> "hello, "        : String +s.object_id    #=> 134667712        : UInt64 +s += "Crystal" #=> "hello, Crystal" : String +s.object_id    #=> 142528472        : UInt64 + +# Поддерживается интерполяция строк +"sum = #{1 + 2}" #=> "sum = 3" : String + +# Поддерживается многострочность +"This is +   multiline string" + +# Строка с двойными кавычками +%(hello "world") #=> "hello \"world\"" + + +# Символы — константы без значения, определяемые только именем. Часто +# используются вместо часто используемых строк для лучшей производительности. +# На внутреннем уровне они представлены как Int32. + +:symbol.class #=> Symbol + +sentence = :question?     # :"question?" : Symbol + +sentence == :question?    #=> true  : Bool +sentence == :exclamation! #=> false : Bool +sentence == "question?"   #=> false : Bool + + +# Массивы + +[1, 2, 3].class         #=> Array(Int32) +[1, "hello", 'x'].class #=> Array(Int32 | String | Char) + +# При объявлении пустого массива необходимо указать тип его элементов +[]               # Syntax error: for empty arrays use '[] of ElementType' +[] of Int32      #=> [] : Array(Int32) +Array(Int32).new #=> [] : Array(Int32) + +# Элементы внутри массива имеют свои индексы +array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] : Array(Int32) +array[0]                #=> 1               : Int32 +array[10]               # raises IndexError +array[-6]               # raises IndexError +array[10]?              #=> nil             : (Int32 | Nil) +array[-6]?              #=> nil             : (Int32 | Nil) + +# Можно получать элементы по индексу с конца +array[-1] #=> 5 + +# С начала и с указанием размера итогового массива +array[2, 3] #=> [3, 4, 5] + +# Или посредством указания диапазона +array[1..3] #=> [2, 3, 4] + +# Добавление в массив +array << 6  #=> [1, 2, 3, 4, 5, 6] + +# Удаление элемента из конца массива +array.pop #=> 6 +array     #=> [1, 2, 3, 4, 5] + +# Удаление элемента из начала массива +array.shift #=> 1 +array       #=> [2, 3, 4, 5] + +# Проверка на наличие элемента в массиве +array.includes? 3 #=> true + +# Синтаксический сахар для массива строк и символов +%w(one two three) #=> ["one", "two", "three"] : Array(String) +%i(one two three) #=> [:one, :two, :three]    : Array(Symbol) + +# Массивоподобный синтаксис используется и для других типов, только если для +# них определены методы .new и #<< +set = Set{1, 2, 3} #=> [1, 2, 3] +set.class          #=> Set(Int32) + +# Вышеприведенное эквивалентно следующему +set = Set(typeof(1, 2, 3)).new +set << 1 +set << 2 +set << 3 + + +# Хэши + +{1 => 2, 3 => 4}.class   #=> Hash(Int32, Int32) +{1 => 2, 'a' => 3}.class #=> Hash(Int32 | Char, Int32) + +# При объявлении пустого хэша необходимо указать типы ключа и значения +{}                     # Syntax error +{} of Int32 => Int32   # {} +Hash(Int32, Int32).new # {} + +# Значения в хэше легко найти по ключу +hash = {"color" => "green", "number" => 5} +hash["color"]        #=> "green" +hash["no_such_key"]  #=> Missing hash key: "no_such_key" (KeyError) +hash["no_such_key"]? #=> nil + +# Проверка наличия ключа в хэше +hash.has_key? "color" #=> true + +# Синтаксический сахар для символьных и строковых ключей +{key1: 'a', key2: 'b'}     # {:key1 => 'a', :key2 => 'b'} +{"key1": 'a', "key2": 'b'} # {"key1" => 'a', "key2" => 'b'} + +# Хэшеподобный синтаксис используется и для других типов, только если для них +# определены методы .new и #[]= +class MyType +  def []=(key, value) +    puts "do stuff" +  end +end + +MyType{"foo" => "bar"} + +# Вышеприведенное эквивалентно следующему +tmp = MyType.new +tmp["foo"] = "bar" +tmp + + +# Диапазоны + +1..10                  #=> Range(Int32, Int32) +Range.new(1, 10).class #=> Range(Int32, Int32) + +# Включающий и исключающий диапазоны +(3..5).to_a  #=> [3, 4, 5] +(3...5).to_a #=> [3, 4] + +# Проверка на вхождение в диапазон +(1..8).includes? 2 #=> true + + +# Кортежи +# Неизменяемые последовательности фиксированного размера, содержащие, +# как правило, элементы разных типов + +{1, "hello", 'x'}.class #=> Tuple(Int32, String, Char) + +# Доступ к элементам осуществляется по индексу +tuple = {:key1, :key2} +tuple[1] #=> :key2 +tuple[2] #=> syntax error : Index out of bound + +# Элементы кортежей можно попарно присвоить переменным +a, b, c = {:a, 'b', "c"} +a #=> :a +b #=> 'b' +c #=> "c" + + +# Процедуры +# Указатели на функцию с необязательным содержимым (замыкание). +# Обычно создаётся с помощью специального литерала -> + +proc = ->(x : Int32) { x.to_s } +proc.class # Proc(Int32, String) +# Или посредством метода .new +Proc(Int32, String).new { |x| x.to_s } + +# Вызываются посредством метода .call +proc.call 10 #=> "10" + + +# Управляющие операторы + +if true +  "if statement" +elsif false +  "else-if, optional" +else +  "else, also optional" +end + +puts "if as a suffix" if true + +# if как часть выражения +a = if 2 > 1 +      3 +    else +      4 +    end + +a #=> 3 + +# Тернарный if +a = 1 > 2 ? 3 : 4 #=> 4 + +# Оператор выбора +cmd = "move" + +action = case cmd +         when "create" +           "Creating..." +         when "copy" +           "Copying..." +         when "move" +           "Moving..." +         when "delete" +           "Deleting..." +end + +action #=> "Moving..." + + +# Циклы + +index = 0 +while index <= 3 +  puts "Index: #{index}" +  index += 1 +end +# Index: 0 +# Index: 1 +# Index: 2 +# Index: 3 + +index = 0 +until index > 3 +  puts "Index: #{index}" +  index += 1 +end +# Index: 0 +# Index: 1 +# Index: 2 +# Index: 3 + +# Но лучше использовать each +(1..3).each do |index| +  puts "Index: #{index}" +end +# Index: 1 +# Index: 2 +# Index: 3 + +# Тип переменной зависит от типа выражения +if a < 3 +  a = "hello" +else +  a = true +end +typeof a #=> (Bool | String) + +if a && b +  # здесь гарантируется, что и a, и b — не nil +end + +if a.is_a? String +  a.class #=> String +end + + +# Методы + +def double(x) +  x * 2 +end + +# Методы (а также любые блоки) всегда возвращают значение последнего выражения +double(2) #=> 4 + +# Скобки можно опускать, если вызов метода не вносит двусмысленности +double 3 #=> 6 + +double double 3 #=> 12 + +def sum(x, y) +  x + y +end + +# Параметры методов перечисляются через запятую +sum 3, 4 #=> 7 + +sum sum(3, 4), 5 #=> 12 + + +# yield + +# У всех методов есть неявный необязательный параметр блока, который можно +# вызвать ключевым словом yield + +def surround +  puts '{' +  yield +  puts '}' +end + +surround { puts "hello world" } + +# { +# hello world +# } + +# Методу можно передать блок +# & — ссылка на переданный блок +def guests(&block) +  block.call "some_argument" +end + +# Методу можно передать список параметров, доступ к ним будет как к массиву +# Для этого используется оператор * +def guests(*array) +  array.each { |guest| puts guest } +end + +# Если метод возвращает массив, можно попарно присвоить значение каждого из его +# элементов переменным +def foods +    ["pancake", "sandwich", "quesadilla"] +end +breakfast, lunch, dinner = foods +breakfast #=> "pancake" +dinner    #=> "quesadilla" + +# По соглашению название методов, возвращающих булево значение, должно +# оканчиваться вопросительным знаком +5.even? # false +5.odd?  # true + +# Если название метода оканчивается восклицательным знаком, по соглашению это +# означает, что метод делает что-то необратимое, например изменяет получателя. +# Некоторые методы имеют две версии: "опасную" версию с !, которая что-то +# меняет, и "безопасную", которая просто возвращает новое значение +company_name = "Dunder Mifflin" +company_name.gsub "Dunder", "Donald"  #=> "Donald Mifflin" +company_name  #=> "Dunder Mifflin" +company_name.gsub! "Dunder", "Donald" +company_name  #=> "Donald Mifflin" + + +# Классы +# Определяются с помощью ключевого слова class + +class Human + +  # Переменная класса является общей для всех экземпляров этого класса +  @@species = "H. sapiens" + +  # Объявление типа переменной name экземпляра класса +  @name : String + +  # Базовый конструктор +  # Значением первого параметра инициализируем переменную @name. +  # То же делаем и со вторым параметром — переменная @age. В случае, если мы +  # не передаём второй параметр, для инициализации @age будет взято значение +  # по умолчанию (в данном случае — 0) +  def initialize(@name, @age = 0) +  end + +  # Базовый метод установки значения переменной +  def name=(name) +    @name = name +  end + +  # Базовый метод получения значения переменной +  def name +    @name +  end + +  # Синтаксический сахар одновременно для двух методов выше +  property :name + +  # А также по отдельности +  getter :name +  setter :name + +  # Метод класса определяется ключевым словом self, чтобы его можно было +  # различить с методом экземпляра класса. Такой метод можно вызвать только +  # на уровне класса, а не экземпляра. +  def self.say(msg) +    puts msg +  end + +  def species +    @@species +  end +end + + +# Создание экземпляра класса +jim = Human.new("Jim Halpert") + +dwight = Human.new("Dwight K. Schrute") + +# Вызов методов экземпляра класса +jim.species #=> "H. sapiens" +jim.name #=> "Jim Halpert" +jim.name = "Jim Halpert II" #=> "Jim Halpert II" +jim.name #=> "Jim Halpert II" +dwight.species #=> "H. sapiens" +dwight.name #=> "Dwight K. Schrute" + +# Вызов метода класса +Human.say("Hi") #=> выведет "Hi" и вернёт nil + +# Переменные экземпляра класса (@) видно только в пределах экземпляра +class TestClass +  @var = "I'm an instance var" +end + +# Переменные класса (@) видны как в экземплярах класса, так и в самом классе +class TestClass +  @@var = "I'm a class var" +end + +# Переменные с большой буквы — это константы +Var = "I'm a constant" +Var = "can't be updated" # Error: already initialized constant Var + +# Примеры + +# Базовый класс +class Human +  @@foo = 0 + +  def self.foo +    @@foo +  end + +  def self.foo=(value) +    @@foo = value +  end +end + +# Класс-потомок +class Worker < Human +end + +Human.foo   #=> 0 +Worker.foo  #=> 0 + +Human.foo = 2 #=> 2 +Worker.foo    #=> 0 + +Worker.foo = 3 #=> 3 +Human.foo   #=> 2 +Worker.foo  #=> 3 + +module ModuleExample +  def foo +    "foo" +  end +end + +# Подключение модуля в класс добавляет его методы в экземпляр класса +# Расширение модуля добавляет его методы в сам класс + +class Person +  include ModuleExample +end + +class Book +  extend ModuleExample +end + +Person.foo     # => undefined method 'foo' for Person:Class +Person.new.foo # => 'foo' +Book.foo       # => 'foo' +Book.new.foo   # => undefined method 'foo' for Book + + +# Обработка исключений + +# Создание пользовательского типа исключения +class MyException < Exception +end + +# Ещё одного +class MyAnotherException < Exception; end + +ex = begin +   raise MyException.new +rescue ex1 : IndexError +  "ex1" +rescue ex2 : MyException | MyAnotherException +  "ex2" +rescue ex3 : Exception +  "ex3" +rescue ex4 # без указания конкретного типа исключения будут "отлавливаться" все +  "ex4" +end + +ex #=> "ex2" + +``` + +## Дополнительная информация + +### На русском + +- [Официальная документация](http://ru.crystal-lang.org/docs/) + +### На английском + +- [Official Documentation](http://crystal-lang.org/) diff --git a/ru-ru/jquery-ru.html.markdown b/ru-ru/jquery-ru.html.markdown new file mode 100644 index 00000000..471b4e24 --- /dev/null +++ b/ru-ru/jquery-ru.html.markdown @@ -0,0 +1,127 @@ +--- +category: tool +tool: jquery +contributors: +    - ["Sawyer Charles", "https://github.com/xssc"] +translators: +    - ["Ev Bogdanov", "https://github.com/evbogdanov"] +lang: ru-ru +filename: jquery-ru.js +--- + +jQuery — это библиотека JavaScript, которая помогает "делать больше, писать меньше". Она выполняет множество типичных JavaScript-задач, упрощая написание кода. jQuery используется крупными компаниями и разработчиками со всего мира. Она упрощает и ускоряет работу с AJAX, с событиями, с DOM и со многим другим. + +Поскольку jQuery является библиотекой JavaScript, вам следует начать с [изучения JavaScript](https://learnxinyminutes.com/docs/ru-ru/javascript-ru/). + +```js + + +/////////////////////////////////// +// 1. Селекторы + +// Для получения элемента в jQuery используются селекторы +var page = $(window); // Получить страницу целиком + +// В качестве селектора может выступать CSS-селектор +var paragraph = $('p'); // Получить все <p> элементы +var table1 = $('#table1'); // Получить элемент с идентификатором 'table1' +var squares = $('.square'); // Получить все элементы с классом 'square' +var square_p = $('p.square') // Получить <p> элементы с классом 'square' + + +/////////////////////////////////// +// 2. События и эффекты +// jQuery прекрасно справляется с обработкой событий +// Часто используемое событие — это событие документа 'ready' +// Вы можете использовать метод 'ready', который сработает, как только документ полностью загрузится +$(document).ready(function(){ +  // Код не выполнится до тех пор, пока документ не будет загружен +}); +// Обработку события можно вынести в отдельную функцию +function onAction() { +  // Код выполнится, когда произойдёт событие +} +$('#btn').click(onAction); // Обработчик события сработает при клике + +// Другие распространённые события: +$('#btn').dblclick(onAction); // Двойной клик +$('#btn').hover(onAction); // Наведение курсора +$('#btn').focus(onAction); // Фокус +$('#btn').blur(onAction); // Потеря фокуса +$('#btn').submit(onAction); // Отправка формы +$('#btn').select(onAction); // Когда выбрали элемент +$('#btn').keydown(onAction); // Когда нажали клавишу +$('#btn').keyup(onAction); // Когда отпустили клавишу +$('#btn').keypress(onAction); // Когда нажали символьную клавишу (нажатие привело к появлению символа) +$('#btn').mousemove(onAction); // Когда переместили курсор мыши +$('#btn').mouseenter(onAction); // Когда навели курсор на элемент +$('#btn').mouseleave(onAction); // Когда сдвинули курсор с элемента + + +// Вы можете не только обрабатывать события, но и вызывать их +$('#btn').dblclick(); // Вызвать двойной клик на элементе + +// Для одного селектора возможно назначить несколько обработчиков событий +$('#btn').on( +  {dblclick: myFunction1} // Обработать двойной клик +  {blur: myFunction1} // Обработать исчезновение фокуса +); + +// Вы можете перемещать и прятать элементы с помощью методов-эффектов +$('.table').hide(); // Спрятать элемент(ы) + +// Обратите внимание: вызов функции в этих методах всё равно спрячет сам элемент +$('.table').hide(function(){ +    // Сначала спрятать элемент, затем вызвать функцию +}); + +// Вы можете хранить селекторы в переменных +var tables = $('.table'); + +// Некоторые основные методы для манипуляций с документом: +tables.hide(); // Спрятать элемент(ы) +tables.show(); // Показать элемент(ы) +tables.toggle(); // Спрятать/показать +tables.fadeOut(); // Плавное исчезновение +tables.fadeIn(); // Плавное появление +tables.fadeToggle(); // Плавное исчезновение или появление +tables.fadeTo(0.5); // Изменение прозрачности +tables.slideUp(); // Свернуть элемент +tables.slideDown(); // Развернуть элемент +tables.slideToggle(); // Свернуть или развернуть + +// Все эти методы принимают скорость (в миллисекундах) и функцию обратного вызова +tables.hide(1000, myFunction); // Анимация длится 1 секунду, затем вызов функции + +// В методе 'fadeTo' вторым параметром обязательно идёт прозрачность +tables.fadeTo(2000, 0.1, myFunction); // Прозрачность меняется в течение 2 секунд до 0.1, затем вызывается функция + +// Метод 'animate' позволяет делать более продвинутую анимацию +tables.animate({"margin-top": "+=50", height: "100px"}, 500, myFunction); + + +/////////////////////////////////// +// 3. Манипуляции + +// Манипуляции похожи на эффекты, но позволяют добиться большего +$('div').addClass('taming-slim-20'); // Добавить класс 'taming-slim-20' ко всем <div> элементам + +// Часто встречающиеся методы манипуляций +$('p').append('Hello world'); // Добавить в конец элемента +$('p').attr('class'); // Получить атрибут +$('p').attr('class', 'content'); // Установить атрибут +$('p').hasClass('taming-slim-20'); // Проверить наличие класса +$('p').height(); // Получить или установить высоту элемента + + +// Во многих методах вам доступна информация ТОЛЬКО о первом элементе из выбранных +$('p').height(); // Вы получите высоту только для первого <p> элемента + +// Метод 'each' позволяет это исправить и пройтись по всем выбранным вами элементам +var heights = []; +$('p').each(function() { +  heights.push($(this).height()); // Добавить высоту всех <p> элементов в массив +}); + + +``` diff --git a/ru-ru/kotlin-ru.html.markdown b/ru-ru/kotlin-ru.html.markdown index 21940e41..58dab4cd 100644 --- a/ru-ru/kotlin-ru.html.markdown +++ b/ru-ru/kotlin-ru.html.markdown @@ -8,7 +8,7 @@ translators:      - ["Vadim Toptunov", "https://github.com/VadimToptunov"]  --- -Kotlin - статистически типизированный язык для JVM, Android и браузера. Язык полностью cjdvtcnbv c Java.  +Kotlin - статистически типизированный язык для JVM, Android и браузера. Язык полностью совместим c Java.   [Более детальная информация здесь.](https://kotlinlang.org/)  ```kotlin diff --git a/ru-ru/markdown-ru.html.markdown b/ru-ru/markdown-ru.html.markdown index ff7a0cc3..579a9a20 100644 --- a/ru-ru/markdown-ru.html.markdown +++ b/ru-ru/markdown-ru.html.markdown @@ -36,13 +36,14 @@ lang: ru-ru  Markdown является надмножеством HTML, поэтому любой HTML-файл является  корректным документом Markdown. - ```markdown + ```md  <!-- Это позволяет использовать напрямую  любые элементы HTML-разметки, такие, например, как этот комментарий.    Встроенные в документ HTML-элементы не затрагиваются парсером Markdown  и попадают в итоговый HTML без изменений. Однако следует понимать,  что эта же особенность не позволяет использовать разметку Markdown внутри  HTML-элементов --> +```  ## Заголовки  @@ -50,7 +51,7 @@ HTML-элементы от <h1> до <h6> размечаются очень пр  текст, который должен стать заголовком, предваряется  соответствующим количеством символов "#": -```markdown +```md  # Это заголовок h1  ## Это заголовок h2  ### Это заголовок h3 @@ -60,7 +61,7 @@ HTML-элементы от <h1> до <h6> размечаются очень пр  ```  Markdown позволяет размечать заголовки <h1> и <h2> ещё одним способом: -```markdown +```md  Это заголовок h1  ================ @@ -72,7 +73,7 @@ Markdown позволяет размечать заголовки <h1> и <h2>   Текст легко сделать полужирным и/или курсивным: -```markdown +```md  *Этот текст будет выведен курсивом.*  _Так же, как этот._ @@ -87,7 +88,7 @@ __И этот тоже.__  В Github Flavored Markdown, стандарте, который используется в Github,  текст также можно сделать зачёркнутым: -```markdown +```md  ~~Зачёркнутый текст.~~  ``` @@ -96,7 +97,7 @@ __И этот тоже.__  Абзацами являются любые строки, следующие друг за другом.  Разделяются же абзацы одной или несколькими пустыми строками: -```markdown +```md  Это абзац. Я печатаю в абзаце, разве это не прикольно?  А тут уже абзац №2. @@ -108,7 +109,7 @@ __И этот тоже.__  Для вставки принудительных переносов можно завершить абзац двумя дополнительными пробелами: -```markdown +```md  Эта строка завершается двумя пробелами (выделите, чтобы увидеть!).    Над этой строкой есть <br />! @@ -116,7 +117,7 @@ __И этот тоже.__  Цитаты размечаются с помощью символа «>»: -```markdown +```md  > Это цитата. В цитатах можно  > принудительно переносить строки, вставляя «>» в начало каждой следующей строки. А можно просто оставлять их достаточно длинными, и такие длинные строки будут перенесены автоматически.  > Разницы между этими двумя подходами к переносу строк нет, коль скоро @@ -133,7 +134,7 @@ __И этот тоже.__  одного из символов «*», «+» или «-»:  (символ должен быть одним и тем же для всех элементов) -```markdown +```md  * Список,  * Размеченный  * Звёздочками @@ -154,7 +155,7 @@ __И этот тоже.__  В нумерованных списках каждая строка начинается  с числа и точки вслед за ним: -```markdown +```md  1. Первый элемент  2. Второй элемент  3. Третий элемент @@ -164,7 +165,7 @@ __И этот тоже.__  любое число в начале каждого элемента, и парсер пронумерует элементы сам!  Правда, злоупотреблять этим не стоит :) -```markdown +```md  1. Первый элемент  1. Второй элемент  1. Третий элемент @@ -173,7 +174,7 @@ __И этот тоже.__  Списки могут быть вложенными: -```markdown +```md  1. Введение  2. Начало работы  3. Примеры использования @@ -184,7 +185,7 @@ __И этот тоже.__  Можно даже делать списки задач. Блок ниже создаёт HTML-флажки.  -```markdown +```md  Для отметки флажка используйте «x»  - [ ] Первая задача  - [ ] Вторая задача @@ -197,7 +198,7 @@ __И этот тоже.__  Фрагменты исходного кода (обычно отмечаемые тегом `<code>`) выделяются просто:  каждая строка блока должна иметь отступ в четыре пробела либо в один символ табуляции. -```markdown +```md      Это код,      причём многострочный  ``` @@ -205,7 +206,7 @@ __И этот тоже.__  Вы также можете делать дополнительные отступы, добавляя символы табуляции  или по четыре пробела: -```markdown +```md      my_array.each do |item|          puts item      end @@ -215,7 +216,7 @@ __И этот тоже.__  не выделяя код в блок. Для этого фрагменты кода нужно обрамлять  символами «`»: -```markdown +```md  Ваня даже не знал, что делает функция `go_to()`!  ``` @@ -237,7 +238,7 @@ end  Разделители (`<hr>`) добавляются вставкой строки из трёх и более  (одинаковых) символов «*» или «-», с пробелами или без них: -```markdown +```md  ***  ---  - - - @@ -251,18 +252,18 @@ end  текст ссылки, заключив его в квадратные скобки,  и сразу после — URL-адрес, заключенный в круглые -```markdown +```md  [Ссылка!](http://test.com/)  ```  Также для ссылки можно указать всплывающую подсказку (`title`), используя  кавычки внутри круглых скобок: -```markdown +```md  [Ссылка!](http://test.com/ "Ссылка на Test.com")  ```  Относительные пути тоже возможны: -```markdown +```md  [Перейти к музыке](/music/).  ``` @@ -290,7 +291,7 @@ Markdown также позволяет размечать ссылку в вид  Разметка изображений очень похожа на разметку ссылок.  Нужно всего лишь добавить перед ссылкой восклицательный знак! -```markdown +```md    ```  Изображения тоже могут быть оформлены, как сноски. @@ -301,20 +302,20 @@ Markdown также позволяет размечать ссылку в вид  ## Разное  ### Автоссылки -```markdown +```md  Ссылка вида <http://testwebsite.com/> эквивалентна  [http://testwebsite.com/](http://testwebsite.com/)  ```  ### Автоссылки для адресов электронной почты -```markdown +```md  <foo@bar.com>  ```  ### Экранирование символов -```markdown +```md  Я хочу напечатать *текст, заключённый в звёздочки*, но я не хочу,  чтобы он был курсивным. Тогда я делаю так:  \*Текст, заключённый в звёздочки\* @@ -324,7 +325,7 @@ Markdown также позволяет размечать ссылку в вид  В Github Flavored Markdown для представления клавиш на клавиатуре  вы можете использовать тег `<kbd>`. -```markdown +```md  Ваш компьютер завис? Попробуйте нажать  <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd>  ``` @@ -334,7 +335,7 @@ Markdown также позволяет размечать ссылку в вид  да и синтаксис имеют не слишком удобный.  Но если очень нужно, размечайте таблицы так: -```markdown +```md  | Столбец 1    | Столбец 2    | Столбец 3    |  | :----------- | :----------: | -----------: |  | Выравнивание | Выравнивание | Выравнивание | @@ -342,7 +343,7 @@ Markdown также позволяет размечать ссылку в вид  ```  Или более компактно -```markdown +```md  Столбец 1|Столбец 2|Столбец 3  :--|:-:|--:  Выглядит|это|страшновато... diff --git a/ru-ru/php-composer-ru.html.markdown b/ru-ru/php-composer-ru.html.markdown new file mode 100644 index 00000000..4bdf1029 --- /dev/null +++ b/ru-ru/php-composer-ru.html.markdown @@ -0,0 +1,197 @@ +--- +category: tool +tool: composer +contributors: +    - ["Brett Taylor", "https://github.com/glutnix"] +translators: +    - ["Aleksey Lysenko", "https://github.com/nasgul"] +filename: LearnComposer-ru.sh +lang: ru-ru +--- + +[Composer](https://getcomposer.org/) — это инструмент управления зависимостями в PHP. +Он позволяет вам декларировать библиотеки, от которых зависит ваш проект, +и он будет управлять ими, то есть устанавливать/обновлять их для вас. + +# Установка + +```sh +# Устанавливаем composer.phar в текущую папку +curl -sS https://getcomposer.org/installer | php +# Если вы используете этот подход, вам нужно будет вызвать Composer следующим образом: +php composer.phar about + +# Устанавливаем бинарный файл в ~/bin/composer +# Примечание: убедитесь, что ~/bin находится в переменной PATH вашего окружения +curl -sS https://getcomposer.org/installer | php -- --install-dir=~/bin --filename=composer +``` + +Пользователи Windows должны следовать +[Инструкциям по установке в Windows ](https://getcomposer.org/doc/00-intro.md#installation-windows) + +## Подтверждение установки + +```sh +# # Проверить версию и перечислить параметры +composer + +# Получить дополнительную помощь для параметров +composer help require + +# Проверить, способен ли Composer делать то, что ему нужно, и обновлён ли он +composer diagnose +composer diag # краткий вариант + +# Обновление Composer до последней версии +composer self-update +composer self # краткий вариант +``` + +# Использование + +Composer сохраняет ваши зависимости проекта в `composer.json`. +Вы можете отредактировать этот файл, но лучше всего позволить Composer управлять им за вас. + +```sh +#  Создать новый проект в текущей папке +composer init +# запускается интерактивная анкета с просьбой предоставить подробную информацию о вашем проекте. +# Вы прекрасно можете оставить ответы пустыми, если не делаете другие проекты  +# зависимыми от создаваемого проекта. + +# Если файл composer.json уже существует, загрузите зависимости +composer install + +# Чтобы загрузить только зависимости для готового продукта, т.е.  +# исключая зависимости для разработки +composer install --no-dev + +# Добавить зависимость для готового продукта к этому проекту +composer require guzzlehttp/guzzle +# выяснит, какая существует последняя версия guzzlehttp / guzzle, +# загрузит её и добавит новую зависимость в поле require файла composer.json. + +composer require guzzlehttp/guzzle:6.0.* +# Загрузит последнюю версию, соответствующую шаблону (например, 6.0.2), +# и добавит зависимость к полю require файла composer.json + +composer require --dev phpunit/phpunit:~4.5.0 +# Добавит как зависимость для разработки. +# Будет использовать последнюю версию> = 4.5.0 и <4.6.0 + +composer require-dev phpunit/phpunit:^4.5.0 +# Добавит как зависимость для разработки. +# Будет использовать последнюю версию> = 4.5.0 и <5.0 + +# Для получения дополнительной информации о совместимости версий Composer см. +# [Документацию Composer по версиям] (https://getcomposer.org/doc/articles/versions.md) + +# Чтобы узнать, какие пакеты доступны для установки и в настоящее время установлены +composer show + +# Чтобы узнать, какие пакеты в настоящее время установлены +composer show --installed + +# Чтобы найти пакет со строкой «mailgun» в названии или описании +composer search mailgun +``` + +[Packagist.org](https://packagist.org/) является основным хранилищем для пакетов Composer. +Существующие сторонние пакеты ищите там. + +## composer.json` и `composer.lock` + +Файл `composer.json` хранит параметры допустимых версий каждой зависимости +вашего проекта, а также другую информацию. + + +Файл `composer.lock` хранит точную загруженную версию каждой зависимости. +Никогда не редактируйте этот файл. + +Если вы включите файл `composer.lock` в свой Git-репозиторий, +каждый разработчик установит версии зависимостей, которые вы используете. +Даже когда будет выпущена новая версия зависимости, Composer продолжит загрузку версии, +записанной в lock-файле. + +```sh +# Если вы хотите обновить все зависимости до новейших версий, +# которые по-прежнему соответствуют вашим предпочтениям для версий +composer update + +# Если вам нужна новая версия определённой зависимости: +composer update phpunit/phpunit + +# Если вы хотите перенести пакет на более новую версию  +#с изменением предпочитаемой версии, +# вам может потребоваться сначала удалить старый пакет и его зависимости. +composer remove --dev phpunit/phpunit +composer require --dev phpunit/phpunit:^5.0 +``` + +## Автозагрузчик + +Composer создаёт класс автозагрузки, который вы можете вызвать +из своего приложения. Вы можете создавать экземпляры классов через пространство имён. + +```php +require __DIR__ . '/vendor/autoload.php'; + +$mailgun = new Mailgun\Mailgun("key"); +``` + +### PSR-4-совместимый автозагрузчик + + +Вы можете добавить в автозагрузчик свои собственные пространства имён. + +Добавьте поле `autoload` в `composer.json`: + +```json +{ +  "autoload": { +    "psr-4": {"Acme\\": "src/"} +  } +} +``` +Это скажет автозагрузчику искать что-либо в пространстве имён `\Acme` в папке `src`. + +Вы также можете использовать +[PSR-0, карту классов или просто список файлов для включения](https://getcomposer.org/doc/04-schema.md#autoload). +Также существует поле `autoload-dev` для пространств имён, предназначенных только для разработки. + +При добавлении или изменении ключа автозагрузки вам необходимо перестроить автозагрузчик: + +```sh +composer dump-autoload +composer dump # краткий вариант + +# Оптимизирует пакеты PSR0 и PSR4 для загрузки классов с помощью карты классов. +# Медленно запускается, но улучшает производительность готового продукта. +composer dump-autoload --optimize --no-dev +``` + +# Кэш Composer + +```sh +# Composer хранит загруженные пакеты для использования в будущем. Очистите кэш с помощью: +composer clear-cache +``` + +# Устранение неполадок + +```sh +composer diagnose +composer self-update +composer clear-cache +``` + +## Темы, которые ещё (пока) не включены в этот учебник + +* Создание и распространение ваших собственных пакетов на Packagist.org или в другом репозитории +* Предварительные и пост-скриптовые перехватчики: запуск задач, +когда происходят определенные события Composer + +### Ссылки + +* [Composer - Dependency Manager for PHP](https://getcomposer.org/) +* [Packagist.org](https://packagist.org/) diff --git a/ru-ru/rust-ru.html.markdown b/ru-ru/rust-ru.html.markdown new file mode 100644 index 00000000..7bd2809a --- /dev/null +++ b/ru-ru/rust-ru.html.markdown @@ -0,0 +1,316 @@ +--- +language: rust + +filename: learnrust-ru.rs +contributors: +    - ["P1start", "http://p1start.github.io/"] +translators: +    - ["Anatolii Kosorukov", "https://github.com/java1cprog"] +lang: ru-ru + +--- + +Rust сочетает в себе низкоуровневый контроль над производительностью  с удобством высокого уровня и предоставляет гарантии  +безопасности. +Он достигает этих целей, не требуя сборщика мусора или времени выполнения, что позволяет использовать библиотеки Rust как замену +для C-библиотек. + +Первый выпуск Rust, 0.1, произошел в январе 2012 года, и в течение 3 лет развитие продвигалось настолько быстро, что до  +недавнего времени использование стабильных выпусков было затруднено, и вместо этого общий совет заключался в том, чтобы  +использовать последние сборки. + +15 мая 2015 года был выпущен Rust 1.0 с полной гарантией обратной совместимости. Усовершенствования времени компиляции и  +других аспектов компилятора в настоящее время доступны в ночных сборках. Rust приняла модель выпуска на поезде с регулярными выпусками каждые шесть недель. Rust 1.1 beta был доступен одновременно с выпуском Rust 1.0. + +Хотя Rust является языком относительно низкого уровня, Rust имеет некоторые функциональные концепции, которые обычно  +встречаются на языках более высокого уровня. Это делает Rust не только быстрым, но и простым и эффективным для ввода кода. + + +```rust +// Это однострочный комментарии +//  + +/// Так выглядит комментарий для документации +/// # Examples +/// +///  +/// let seven  = 7 +///  + +/////////////// +// 1. Основы // +/////////////// + +// Функции +// `i32` это целочисленный знаковый тип 32-bit +#[allow(dead_code)] +fn add2(x: i32, y: i32) -> i32 { +    // метод возвращает сумму x и y +    x + y +} + +// Главная функция программы +#[allow(unused_variables)] +#[allow(unused_assignments)] +#[allow(dead_code)] +fn main() { +    // Числа // + +    // неизменяемая переменная +    let x: i32 = 1; + +    // Суффиксы целое/дробное +    let y: i32 = 13i32; +    let f: f64 = 1.3f64; + +    // Автоматическое выявление типа данных +    // В большинстве случаев компилятор Rust может вычислить  +	// тип переменной, поэтому +    // вам не нужно писать явные аннотации типа. + +    let implicit_x = 1; +    let implicit_f = 1.3; + +    // Арифметика +    let sum = x + y + 13; + +    // Изменяемая переменная +    let mut mutable = 1; +    mutable = 4; +    mutable += 2; + +    // Строки // + +    // Строковые литералы +    let x: &str = "hello world!"; + +    // Печать на консоль +    println!("{} {}", f, x); // 1.3 hello world + +    // `String` – изменяемя строка +    let s: String = "hello world".to_string(); + +    // Строковый срез - неизменяемый вид в строки +    // Это в основном неизменяемая пара указателей на строку - +    // Это указатель на начало и конец строкового буфера + +    let s_slice: &str = &s; + +    println!("{} {}", s, s_slice); // hello world hello world + +    // Vectors/arrays // + +    // фиксированный массив +    let four_ints: [i32; 4] = [1, 2, 3, 4]; + +    // динамический массив +    let mut vector: Vec<i32> = vec![1, 2, 3, 4]; +    vector.push(5); + +    // Срез - неизменяемое представление значений вектора +    let slice: &[i32] = &vector; + +    // Используйте шаблон `{:?}`для печати отладочной информации структур с данными +    println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] + +    // Кортежи // + +    // Кортеж - это фиксированный набор.  +    // В нём могут находиться значения разных типов данных. +    let x: (i32, &str, f64) = (1, "hello", 3.4); + +    // Инициализация группы переменных `let` +    let (a, b, c) = x; +    println!("{} {} {}", a, b, c); // 1 hello 3.4 + +    // Доступ по индексу +    println!("{}", x.1); // hello + +    ////////////// +    // 2. Типы // +    ////////////// + +    // Struct +    struct Point { +        x: i32, +        y: i32, +    } + +    let origin: Point = Point { x: 0, y: 0 }; + +    // Структуры могут быть с безымянными полями ‘tuple struct’ +    struct Point2(i32, i32); + +    let origin2 = Point2(0, 0); + +    // Перечисление +    enum Direction { +        Left, +        Right, +        Up, +        Down, +    } + +    let up = Direction::Up; + +    // Перечисление с полями +    enum OptionalI32 { +        AnI32(i32), +        Nothing, +    } + +    let two: OptionalI32 = OptionalI32::AnI32(2); +    let nothing = OptionalI32::Nothing; + +    // Обобщенные типы данных // + +    struct Foo<T> { bar: T } + +    // Частоиспользуемое перечисление стандартной библиотеки `Option` +    enum Optional<T> { +        SomeVal(T), +        NoVal, +    } + +    // Методы // + +    impl<T> Foo<T> { +            fn get_bar(self) -> T { +            self.bar +        } +    } + +    let a_foo = Foo { bar: 1 }; +    println!("{}", a_foo.get_bar()); // 1 + +    // Типаж + +    trait Frobnicate<T> { +        fn frobnicate(self) -> Option<T>; +    } + +    impl<T> Frobnicate<T> for Foo<T> { +        fn frobnicate(self) -> Option<T> { +            Some(self.bar) +        } +    } + +    let another_foo = Foo { bar: 1 }; +    println!("{:?}", another_foo.frobnicate()); // Some(1) + +    ///////////////////////// +    // 3. Поиск по шаблону // +    ///////////////////////// + +    let foo = OptionalI32::AnI32(1); +    match foo { +        OptionalI32::AnI32(n) => println!("it’s an i32: {}", n), +        OptionalI32::Nothing  => println!("it’s nothing!"), +    } + +    // Более сложный пример +    struct FooBar { x: i32, y: OptionalI32 } +    let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) }; + +    match bar { +        FooBar { x: 0, y: OptionalI32::AnI32(0) } => +            println!("The numbers are zero!"), +        FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m => +            println!("The numbers are the same"), +        FooBar { x: n, y: OptionalI32::AnI32(m) } => +            println!("Different numbers: {} {}", n, m), +        FooBar { x: _, y: OptionalI32::Nothing } => +            println!("The second number is Nothing!"), +    } + +    ///////////////////// +    // 4. Управление ходом выполнения программы // +    ///////////////////// + +    // `for` loops/iteration +    let array = [1, 2, 3]; +    for i in array.iter() { +        println!("{}", i); +    } + +    // Отрезки +    for i in 0u32..10 { +        print!("{} ", i); +    } +    println!(""); +    // prints `0 1 2 3 4 5 6 7 8 9 ` + +    // `if` +    if 1 == 1 { +        println!("Maths is working!"); +    } else { +        println!("Oh no..."); +    } + +    // `if` as expression +    let value = if true { +        "good" +    } else { +        "bad" +    }; + +    // `while` loop +    while 1 == 1 { +        println!("The universe is operating normally."); +        break; +    } + +    // Infinite loop +    loop { +        println!("Hello!"); +        break; +    } + +    ///////////////////////////////// +    // 5. Защита памяти и указатели // +    ///////////////////////////////// + +    // Владеющий указатель – такой указатель может быть только один +    // Это значит, что при вызоде из блока переменная автоматически становится недействительной. +    let mut mine: Box<i32> = Box::new(3); +    *mine = 5; // dereference +    // Здесь, `now_its_mine` получает во владение `mine`. Т.е. `mine` была перемещена. +    let mut now_its_mine = mine; +    *now_its_mine += 2; + +    println!("{}", now_its_mine); // 7 +    // println!("{}", mine);   + +    //  Ссылки - это неизменяемые указатели +    //  Если ссылка получает значения, то говорят, что она заимствует это значение. +    //  Такое значение не может быть изменено или перемещено. +    let mut var = 4; +    var = 3; +    let ref_var: &i32 = &var; + +    println!("{}", var); +    println!("{}", *ref_var); +    // var = 5; // не скомпилируется +    // *ref_var = 6; // и это + +    // Изменяемые ссылки +    // +    let mut var2 = 4; +    let ref_var2: &mut i32 = &mut var2; +    *ref_var2 += 2;         // '*' используется для изменения значения + +    println!("{}", *ref_var2); // 6 , // var2 would not compile. +    // ref_var2 имеет тип &mut i32, т.е. он содержит ссылку на i32, а не значение. +    // var2 = 2; // не скомпилируется, т.к. эта переменная уже была заимствована ранее +}  + +``` + +## Более подробная информация о языке + +Уже есть хорошие книги для изучающих Rust. Основным источником остаётся  +[The Rust Programming Language](http://doc.rust-lang.org/book/index.html)  + +Для компиляции программ при изучении языка весьма удобно использовать  +[Rust playpen](http://play.rust-lang.org).  +Множество ресурсов на разных языках можно найти в [этом проекте](https://github.com/ctjhoa/rust-learning). diff --git a/ru-ru/yaml-ru.html.markdown b/ru-ru/yaml-ru.html.markdown new file mode 100644 index 00000000..6eb580d9 --- /dev/null +++ b/ru-ru/yaml-ru.html.markdown @@ -0,0 +1,189 @@ +--- +language: yaml +filename: learnyaml-ru.yaml +contributors: +- [Adam Brenecki, 'https://github.com/adambrenecki'] +- [Suhas SG, 'https://github.com/jargnar'] +translators: +- [Sergei Babin, 'https://github.com/serzn1'] +lang: ru-ru +--- + +YAML как язык сериализации данных предназначен прежде всего для использования людьми. + +Это строгое надмножество JSON с добавлением синтаксически значимых переносов строк и  +отступов как в Python. Тем не менее, в отличие от Python, YAML запрещает  +использование табов для отступов. + +```yaml +---  # начало документа + +# Комментарий в YAML выглядит как-то так. + +###################### +# Скалярные величины # +###################### + +# Наш корневой объект (который продолжается для всего документа) будет соответствовать +# типу map, который в свою очередь соответствует словарю, хешу или объекту в других языках. +key: value +another_key: Другое значение ключа. +a_number_value: 100 +scientific_notation: 1e+12 +# Число 1 будет интерпретировано как число, а не как логический тип. Если необходимо чтобы +# значение было интерпретировано как логическое, необходимо использовать true +boolean: true +null_value: null +key with spaces: value + +# Обратите внимание что строки используются без кавычек, но могут и с кавычками. +however: 'Строка заключенная в кавычки.' +'Ключ заключенный в кавычки.': "Полезно если нужно использовать ':' в вашем ключе." +single quotes: 'Содержит ''одну'' экранированную строку' +double quotes: "Содержит несколько: \", \0, \t, \u263A, \x0d\x0a == \r\n, экранированных строк." + +# Многострочные строковые значения могут быть записаны как 'строковый блок' (используя |), +# или как 'сложенный блок' (используя '>'). +literal_block: | +    Значение всего текста в этом блоке будет присвоено ключу 'literal_block', +    с сохранением переноса строк. + +    Объявление продолжается до удаления отступа и выравнивания с ведущим отступом. + +        Любые строки с большим отступом сохраняют остатки своего отступа -   +        эта строка будет содержать дополнительно 4 пробела. +folded_style: > +    Весь блок этого тектса будет значением 'folded_style', но в данном случае +    все символы новой строки будут заменены пробелами. + +    Пустые строки будут преобразованы в перенос строки. + +        Строки с дополнительными отступами сохраняют их переносы строк - +        этот текст появится через 2 строки. + +################## +# Типы коллекций # +################## + +# Вложения используют отступы. Отступ в 2 пробела предпочтителен (но не обязателен). +a_nested_map: +  key: value +  another_key: Another Value +  another_nested_map: +    hello: hello + +# В словарях (maps) используются не только строковые значения ключей. +0.25: a float key + +# Ключи также могут быть сложными, например многострочными. +# Мы используем ? с последующим пробелом чтобы обозначить начало сложного ключа. +? | +  Этот ключ +  который содержит несколько строк +: и это его значение + +# YAML также разрешает соответствия между последовательностями со сложными ключами +# Некоторые парсеры могут выдать предупреждения или ошибку +# Пример +? - Manchester United +  - Real Madrid +: [2001-01-01, 2002-02-02] + +# Последовательности (эквивалент списка или массива) выглядят как-то так +# (обратите внимание что знак '-' считается отступом): +a_sequence: +  - Item 1 +  - Item 2 +  - 0.5  # последовательности могут содержать различные типы. +  - Item 4 +  - key: value +    another_key: another_value +  - +    - Это последовательность +    - внутри другой последовательности +  - - - Объявления вложенных последовательностей +      - могут быть сжаты + +# Поскольку YAML это надмножество JSON, вы можете использовать JSON-подобный  +# синтаксис для словарей и последовательностей: +json_map: {"key": "value"} +json_seq: [3, 2, 1, "takeoff"] +в данном случае кавычки не обязательны: {key: [3, 2, 1, takeoff]} + +########################## +# Дополнительные функции # +########################## + +# В YAML есть удобная система так называемых 'якорей' (anchors), которые позволяют легко +# дублировать содержимое внутри документа. Оба ключа в примере будут иметь одинаковые значения: +anchored_content: &anchor_name Эта строка будет являться значением обоих ключей. +other_anchor: *anchor_name + +# Якоря могут использоваться для дублирования/наследования свойств +base: &base +  name: Каждый будет иметь одинаковое имя + +# Регулярное выражение << называется ключом объединения независимо от типа языка. +# Он используется чтобы показать что все ключи одного или более словарей должны быть +# добавлены в текущий словарь. + +foo: &foo +  <<: *base +  age: 10 + +bar: &bar +  <<: *base +  age: 20 + +# foo и bar могли бы иметь имена: Каждый из них имеет аналогичное имя + +# В YAML есть теги (tags), которые используются для явного объявления типов. +explicit_string: !!str 0.5 +# В некоторых парсерах реализованы теги для конкретного языка, пример для Python +# пример сложного числового типа. +python_complex_number: !!python/complex 1+2j + +# Мы можем использовать сложные ключи с включенными в них тегами из определенного языка +? !!python/tuple [5, 7] +: Fifty Seven +# Могло бы быть {(5, 7): 'Fifty Seven'} в Python + +####################### +# Дополнительные типы # +####################### + +# Строки и числа не единственные величины которые может понять YAML. +# YAML также поддерживает даты и время в формате ISO. +datetime: 2001-12-15T02:59:43.1Z +datetime_with_spaces: 2001-12-14 21:59:43.10 -5 +date: 2002-12-14 + +# Тег !!binary показывает что эта строка является base64-закодированным +# представлением двоичного объекта. +gif_file: !!binary | +  R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 +  OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ +  +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC +  AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= + +# YAML может использовать объекты типа ассоциативных массивов (set), как представлено ниже: +set: +  ? item1 +  ? item2 +  ? item3 +or: {item1, item2, item3} + +# Сеты (set) являются простыми эквивалентами словарей со значениями  +# типа null; запись выше эквивалентна следующей: +set2: +  item1: null +  item2: null +  item3: null + +...  # конец документа +``` + +### Больше информации + ++ [YAML оффициальный вебсайт](http://yaml.org/) ++ [YAML онлайн валидатор](http://www.yamllint.com/) | 
