diff options
Diffstat (limited to 'ru-ru')
37 files changed, 6035 insertions, 698 deletions
| diff --git a/ru-ru/.directory b/ru-ru/.directory deleted file mode 100644 index 4d20336b..00000000 --- a/ru-ru/.directory +++ /dev/null @@ -1,4 +0,0 @@ -[Dolphin] -SortRole=size -Timestamp=2015,10,31,18,6,13 -Version=3 diff --git a/ru-ru/asymptotic-notation-ru.html.markdown b/ru-ru/asymptotic-notation-ru.html.markdown new file mode 100644 index 00000000..7fd02c47 --- /dev/null +++ b/ru-ru/asymptotic-notation-ru.html.markdown @@ -0,0 +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://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/bf.html.markdown b/ru-ru/bf.html.markdown index 20f0fa56..d2e74e8f 100644 --- a/ru-ru/bf.html.markdown +++ b/ru-ru/bf.html.markdown @@ -1,5 +1,6 @@  ---  language: bf +filename: learnbf-ru.bf  contributors:      - ["Prajit Ramachandran", "http://prajitr.github.io/"]      - ["Mathias Bynens", "http://mathiasbynens.be/"] diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown index 0cf580d5..3acfafa3 100644 --- a/ru-ru/c++-ru.html.markdown +++ b/ru-ru/c++-ru.html.markdown @@ -43,11 +43,11 @@ int main(int argc, char** argv)      // Аргументы командной строки, переданные в программу, хранятся в переменных  	// argc и argv, так же, как и в C.      // argc указывает на количество аргументов, -    // а argv является массивом C-подобных строк (char*), который непосредсвенно +    // а argv является массивом C-подобных строк (char*), который непосредственно  	// содержит аргументы.      // Первым аргументом всегда передается имя программы. -    // argc и argv могут быть опущены, если вы не планируете работать с аругментами -	// коммандной строки. +    // argc и argv могут быть опущены, если вы не планируете работать с аргументами +	// командной строки.  	// Тогда сигнатура функции будет иметь следующий вид: int main()      // Возвращаемое значение 0 указывает на успешное завершение программы. @@ -162,7 +162,7 @@ void foo()  int main()  { -    // Включает все функци из пространства имен Second в текущую область видимости. +    // Включает все функции из пространства имен Second в текущую область видимости.      // Обратите внимание, что простой вызов foo() больше не работает,      // так как теперь не ясно, вызываем ли мы foo из пространства имен Second, или  	// из глобальной области видимости. @@ -304,7 +304,7 @@ someFun(tempObjectFun());  // Выполняет версию с временн  basic_string(const basic_string& other);  basic_string(basic_string&& other); -// Идея в том, что если мы конструируем новую строку из временного объекта (который  +// Идея в том, что если мы конструируем новую строку из временного объекта (который  // так или иначе будет уничтожен), мы можем использовать более эффективный конструктор,  // который "спасает" части этой временной строки. Эта концепция была названа  // "move semantics". @@ -329,7 +329,7 @@ ECarTypes GetPreferredCarType()  }  // На момент выхода C++11 есть простой способ назначения типа перечисления, что -// полезно в случае сериализации данных и преобразований между конечным типом и  +// полезно в случае сериализации данных и преобразований между конечным типом и  // соответствующими константами.  enum ECarTypes : uint8_t  { @@ -453,7 +453,7 @@ void Dog::print() const  Dog::~Dog()  { -    cout << "Goodbye " << name << "\n"; +    std::cout << "Goodbye " << name << "\n";  }  int main() { @@ -471,6 +471,7 @@ int main() {  // членам\методам без открытых или защищенных методов для этого.  class OwnedDog : public Dog { +public:      void setOwner(const std::string& dogsOwner);      // Переопределяем поведение функции печати для всех OwnedDog. Смотрите @@ -521,7 +522,7 @@ public:      // по умолчанию (0, 0)      Point() { }; -    // Следующий синтаксис известен как список инициализации и является верным способом  +    // Следующий синтаксис известен как список инициализации и является верным способом  	// инициализировать значения членов класса.      Point (double a, double b) :          x(a), @@ -582,10 +583,10 @@ public:  // Во время компиляции компилятор фактически генерирует копии каждого шаблона  // с замещенными параметрами, поэтому полное определение класса должно присутствовать -// при каждом вызове. Именно поэтому классы шаблонов полностью определены в +// при каждом вызове. Именно поэтому шаблоны классов полностью определены в  // заголовочных файлах. -// Чтобы создать экземпляр класса шаблона на стеке: +// Чтобы создать экземпляр шаблона класса на стеке:  Box<int> intBox;  // и вы можете использовать его, как и ожидалось: @@ -605,7 +606,7 @@ boxOfBox.insert(intBox);  //   http://en.wikipedia.org/wiki/Typename  // (да-да, это ключевое слово имеет собственную страничку на вики). -// Аналогичным образом, шаблонная функция: +// Аналогичным образом, шаблон функции:  template<class T>  void barkThreeTimes(const T& input)  { @@ -622,7 +623,7 @@ Dog fluffy;  fluffy.setName("Fluffy");  barkThreeTimes(fluffy); // Печатает "Fluffy barks" три раза. -//Параметры шаблона не должны быть классами: +// Параметры шаблона не должны быть классами:  template<int Y>  void printMessage() {    cout << "Learn C++ in " << Y << " minutes!" << endl; @@ -680,7 +681,7 @@ catch (...)  // некоторого ресурса неразрывно совмещается с инициализацией, а освобождение -  // с уничтожением объекта. -// Чтобы понять, на сколько это полезно, +// Чтобы понять, насколько это полезно,  // рассмотрим функцию, которая использует обработчик файлов в С:  void doSomethingWithAFile(const char* filename)  { @@ -793,10 +794,10 @@ void doSomethingWithAFile(const std::string& filename)  // Весь идиоматический код на С++ широко использует RAII для всех ресурсов.  // Дополнительные примеры включат:  // - Использование памяти unique_ptr и shared_ptr -// - Контейнеры - стандартная библиотека связанных списков, векторы  +// - Контейнеры - стандартная библиотека связанных списков, векторы  //   (т.е. самоизменяемые массивы), хэш-таблицы и все остальное автоматически  //    уничтожается сразу же, когда выходит за пределы области видимости. -// - Ипользование мьютексов lock_guard и unique_lock +// - Использование мьютексов lock_guard и unique_lock  // Контейнеры с пользовательскими классами в качестве ключей требуют  // сравнивающих функций в самом объекте или как указатель на функцию. Примитивы @@ -853,7 +854,7 @@ pt2 = nullptr;  // Устанавливает pt2 в null.  // '=' != '=' != '='!  // Вызывает Foo::Foo(const Foo&) или некий вариант (смотрите "move semantics") -// копирования конструктора. +// конструктора копирования.  Foo f2;  Foo f1 = f2; @@ -886,7 +887,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/c-ru.html.markdown b/ru-ru/c-ru.html.markdown index ab4be57e..cc68d620 100644 --- a/ru-ru/c-ru.html.markdown +++ b/ru-ru/c-ru.html.markdown @@ -11,7 +11,7 @@ lang: ru-ru  Что ж, Си всё ещё является лидером среди современных высокопроизводительных языков. -Для большинствоа программистов, Си – это самый низкоуровневый язык на котором они когда-либо писали, +Для большинства программистов, Си – это самый низкоуровневый язык на котором они когда-либо писали,  но этот язык даёт больше, чем просто повышение производительности.  Держите это руководство в памяти и вы сможете использовать Си максимально эффективно. @@ -77,7 +77,7 @@ int main() {      // sizeof(obj) возвращает размер объекта obj в байтах.      printf("%zu\n", sizeof(int)); // => 4 (на большинстве машин int занимает 4 байта) -    // Если аргуметом sizeof будет выражение, то этот аргумент вычисляется +    // Если аргументом sizeof будет выражение, то этот аргумент вычисляется      // ещё во время компиляции кода (кроме динамических массивов).      int a = 1;      // size_t это беззнаковый целый тип который использует как минимум 2 байта @@ -170,7 +170,7 @@ int main() {      !0; // => 1      1 && 1; // => 1 (логическое И)      0 && 1; // => 0 -    0 || 1; // => 1 (лигическое ИЛИ) +    0 || 1; // => 1 (логическое ИЛИ)      0 || 0; // => 0      // Битовые операторы @@ -229,7 +229,7 @@ int main() {      switch (some_integral_expression) {      case 0: // значения должны быть целыми константами (и могут быть выражениями)          do_stuff(); -        break; // если не написать break; то управление будет передено следующему блоку +        break; // если не написать break; то управление будет передано следующему блоку      case 1:          do_something_else();          break; @@ -247,7 +247,7 @@ int main() {      // Каждое выражение в Си имеет тип, но вы можете привести один тип к другому,       // если хотите (с некоторыми искажениями). -    int x_hex = 0x01; // Вы можете назначать переменные с помощью шеснадцатеричного кода. +    int x_hex = 0x01; // Вы можете назначать переменные с помощью шестнадцатеричного кода.      // Приведение типов будет пытаться сохранять цифровые значения.      printf("%d\n", x_hex); // => Prints 1 @@ -288,14 +288,14 @@ int main() {      // Для того, чтобы получить значение по адресу, напечатайте * перед именем.      // Да, * используется при объявлении указателя и для получении значения по адресу      // немного запутано, но вы привыкнете. -    printf("%d\n", *px); // => Напечаатет 0, значение перемененной x +    printf("%d\n", *px); // => Напечатает 0, значение перемененной x      // Вы также можете изменять значение, на которое указывает указатель.      (*px)++; // Инкрементирует значение на которое указывает px на единицу      printf("%d\n", *px); // => Напечатает 1      printf("%d\n", x); // => Напечатает 1 -    // Массивы удобно использовать для болшого количества однотипных данных. +    // Массивы удобно использовать для большого количества однотипных данных.      int x_array[20];      int xx;      for (xx = 0; xx < 20; xx++) { @@ -308,7 +308,7 @@ int main() {      // Это работает, потому что при обращении к имени массива возвращается       // указатель на первый элемент.      // Например, когда массив передаётся в функцию или присваивается указателю, он -    // невявно преобразуется в указатель. +    // неявно преобразуется в указатель.      // Исключения: когда массив является аргументом для оператор '&':      int arr[10];      int (*ptr_to_arr)[10] = &arr; // &arr не является 'int *'! @@ -335,7 +335,7 @@ int main() {      // Работа с памятью с помощью указателей может давать неожиданные и      // непредсказуемые результаты. -    printf("%d\n", *(my_ptr + 21)); // => Напечатает кто-нибудь-знает-что?  +    printf("%d\n", *(my_ptr + 21)); // => Напечатает кто-нибудь знает, что?                                       // Скорей всего программа вылетит.      // Когда вы закончили работать с памятью, которую ранее выделили, вам необходимо  @@ -353,7 +353,7 @@ int main() {      // Это не работает, если строка является массивом      // (потенциально задаваемой с помощью строкового литерала) -    // который находиться в перезаписываемой части памяти: +    // который находится в перезаписываемой части памяти:      char foo[] = "foo";      foo[0] = 'a'; // это выполнится и строка теперь "aoo" @@ -426,7 +426,7 @@ void function_1() {      // Можно получить доступ к структуре и через указатель      (*my_rec_ptr).width = 30; -    // ... или ещё лучше: используйте оператор -> для лучшей читабельночти +    // ... или ещё лучше: используйте оператор -> для лучшей читабельности      my_rec_ptr->height = 10; // то же что и "(*my_rec_ptr).height = 10;"  } @@ -457,7 +457,7 @@ int area(const rect *r) {  void str_reverse_through_pointer(char *str_in) {      // Определение функции через указатель. -    void (*f)(char *); // Сигнатура должна полность совпадать с целевой функцией. +    void (*f)(char *); // Сигнатура должна полностью совпадать с целевой функцией.      f = &str_reverse; // Присвоить фактический адрес (во время исполнения)      // "f = str_reverse;" тоже будет работать.      //Имя функции (как и массива) возвращает указатель на начало. @@ -471,13 +471,13 @@ void str_reverse_through_pointer(char *str_in) {  Лучше всего найдите копию [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language)  Это **книга** написанная создателями Си. Но будьте осторожны, она содержит идеи которые больше не считаются хорошими. -Другой хороший ресурс: [Learn C the hard way](http://c.learncodethehardway.org/book/). +Другой хороший ресурс: [Learn C the hard way](http://learncodethehardway.org/c/).  Если у вас появился вопрос, почитайте [compl.lang.c Frequently Asked Questions](http://c-faq.com).  Очень важно использовать правильные отступы и ставить пробелы в нужных местах.  Читаемый код лучше чем красивый или быстрый код. -Чтобы научиться писать хороший код, почитайте [Linux kernel coding stlye](https://www.kernel.org/doc/Documentation/CodingStyle). +Чтобы научиться писать хороший код, почитайте [Linux kernel coding style](https://www.kernel.org/doc/Documentation/CodingStyle).  Также не забывайте, что [Google](http://google.com) и [Яндекс](http://yandex.ru) – ваши хорошие друзья. diff --git a/ru-ru/clojure-ru.html.markdown b/ru-ru/clojure-ru.html.markdown index 451da312..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) @@ -321,7 +321,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут  ; Также модуль может быть импортирован формой require  (require 'clojure.string) -; После этого модуль становится доступе в текущем пространстве имен, +; После этого модуль становится доступен в текущем пространстве имен,  ; а вызов его функций может быть осуществлен указанием полного имени функции:  (clojure.string/blank? "") ; => true @@ -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/css-ru.html.markdown b/ru-ru/css-ru.html.markdown index 2e2d40b7..e0e5e30b 100644 --- a/ru-ru/css-ru.html.markdown +++ b/ru-ru/css-ru.html.markdown @@ -116,7 +116,7 @@ element:visited {}  /* или еще не проходил по ней */  element:link {} -/* выбранное поле воода (input) */ +/* выбранное поле ввода (input) */  element:focus {} @@ -132,7 +132,7 @@ selector {      width: 200px; /* пиксели */      font-size: 20pt; /* пункты */      width: 5cm; /* сантиметры */ -    min-width: 50mm; /* милиметры */ +    min-width: 50mm; /* миллиметры */      max-width: 5in; /* дюймы */      height: 0.2vh; /* умножается на высоту окна браузера (CSS3) */      width: 0.4vw; /* умножается на ширину окна браузера (CSS3) */ @@ -235,7 +235,7 @@ p { property: value !important; }  ## Совместимость -Несмотря на то, что большая часть функций CSS2 (а также CSS3) подеррживается всеми +Несмотря на то, что большая часть функций CSS2 (а также CSS3) поддерживается всеми  браузерами и устройствами, не забывайте проверять совместимость CSS-правил  с современными браузерами. diff --git a/ru-ru/elixir-ru.html.markdown b/ru-ru/elixir-ru.html.markdown new file mode 100644 index 00000000..c8c2c060 --- /dev/null +++ b/ru-ru/elixir-ru.html.markdown @@ -0,0 +1,467 @@ +--- +language: elixir +contributors: +    - ["Joao Marques", "http://github.com/mrshankly"] +    - ["Dzianis Dashkevich", "https://github.com/dskecse"] +    - ["Ryan Plant", "https://github.com/ryanplant-au"] +translator: +    - ["Ev Bogdanov", "https://github.com/evbogdanov"] +filename: learnelixir-ru.ex +lang: ru-ru +--- + +Elixir — современный функциональный язык программирования, который работает на +виртуальной машине Erlang. Elixir полностью совместим с Erlang, но обладает +дружелюбным синтаксисом и предлагает больше возможностей. + +```elixir + +# Однострочные комментарии начинаются с символа решётки. + +# Для многострочных комментариев отдельного синтаксиса нет, +# поэтому просто используйте несколько однострочных комментариев. + +# Запустить интерактивную Elixir-консоль (аналог `irb` в Ruby) можно +# при помощи команды `iex`. +# Чтобы скомпилировать модуль, воспользуйтесь командой `elixirc`. + +# Обе команды будут работать из терминала, если вы правильно установили Elixir. + +## --------------------------- +## -- Базовые типы +## --------------------------- + +# Числа +3    # целое число +0x1F # целое число +3.0  # число с плавающей запятой + +# Атомы, которые являются нечисловыми константами. Они начинаются с символа `:`. +:hello # атом + +# Кортежи, которые хранятся в памяти последовательно. +{1,2,3} # кортеж + +# Получить доступ к элементу кортежа мы можем с помощью функции `elem`: +elem({1, 2, 3}, 0) #=> 1 + +# Списки, которые реализованы как связные списки. +[1,2,3] # список + +# У каждого непустого списка есть голова (первый элемент списка) +# и хвост (все остальные элементы списка): +[head | tail] = [1,2,3] +head #=> 1 +tail #=> [2,3] + +# В Elixir, как и в Erlang, знак `=` служит для сопоставления с образцом, +# а не для операции присваивания. +# +# Это означает, что выражение слева от знака `=` (образец) сопоставляется с +# выражением справа. +# +# Сопоставление с образцом позволило нам получить голову и хвост списка +# в примере выше. + +# Если выражения слева и справа от знака `=` не удаётся сопоставить, будет +# брошена ошибка. Например, если кортежи разных размеров. +{a, b, c} = {1, 2} #=> ** (MatchError) + +# Бинарные данные +<<1,2,3>> + +# Вы столкнётесь с двумя видами строк: +"hello" # Elixir-строка (заключена в двойные кавычки) +'hello' # Erlang-строка (заключена в одинарные кавычки) + +# Все строки представлены в кодировке UTF-8: +"привет" #=> "привет" + +# Многострочный текст +""" +Я текст на несколько +строк. +""" +#=> "Я текст на несколько\nстрок.\n" + +# Чем Elixir-строки отличаются от Erlang-строк? Elixir-строки являются бинарными +# данными. +<<?a, ?b, ?c>> #=> "abc" +# Erlang-строка — это на самом деле список. +[?a, ?b, ?c]   #=> 'abc' + +# Оператор `?` возвращает целое число, соответствующее данному символу. +?a #=> 97 + +# Для объединения бинарных данных (и Elixir-строк) используйте `<>` +<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>> +"hello " <> "world"  #=> "hello world" + +# Для объединения списков (и Erlang-строк) используйте `++` +[1,2,3] ++ [4,5]     #=> [1,2,3,4,5] +'hello ' ++ 'world'  #=> 'hello world' + +# Диапазоны записываются как `начало..конец` (оба включительно) +1..10 #=> 1..10 + +# Сопоставление с образцом применимо и для диапазонов: +lower..upper = 1..10 +[lower, upper] #=> [1, 10] + +# Карты (известны вам по другим языкам как ассоциативные массивы, словари, хэши) +genders = %{"david" => "male", "gillian" => "female"} +genders["david"] #=> "male" + +# Для карт, где ключами выступают атомы, доступен специальный синтаксис +genders = %{david: "male", gillian: "female"} +genders.gillian #=> "female" + +## --------------------------- +## -- Операторы +## --------------------------- + +# Математические операции +1 + 1  #=> 2 +10 - 5 #=> 5 +5 * 2  #=> 10 +10 / 2 #=> 5.0 + +# В Elixir оператор `/` всегда возвращает число с плавающей запятой. + +# Для целочисленного деления применяйте `div` +div(10, 2) #=> 5 + +# Для получения остатка от деления к вашим услугам `rem` +rem(10, 3) #=> 1 + +# Булевые операторы: `or`, `and`, `not`. +# В качестве первого аргумента эти операторы ожидают булевое значение. +true and true #=> true +false or true #=> true +1 and true    #=> ** (BadBooleanError) + +# Elixir также предоставляет `||`, `&&` и `!`, которые принимают аргументы +# любого типа. Всё, кроме `false` и `nil`, считается `true`. +1 || true  #=> 1 +false && 1 #=> false +nil && 20  #=> nil +!true #=> false + +# Операторы сравнения: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<`, `>` +1 == 1 #=> true +1 != 1 #=> false +1 < 2  #=> true + +# Операторы `===` и `!==` более строгие. Разница заметна, когда мы сравниваем +# числа целые и с плавающей запятой: +1 == 1.0  #=> true +1 === 1.0 #=> false + +# Elixir позволяет сравнивать значения разных типов: +1 < :hello #=> true + +# При сравнении разных типов руководствуйтесь следующим правилом: +# число < атом < ссылка < функция < порт < процесс < кортеж < список < строка + +## --------------------------- +## -- Порядок выполнения +## --------------------------- + +# Условный оператор `if` +if false do +  "Вы этого никогда не увидите" +else +  "Вы увидите это" +end + +# Противоположный ему условный оператор `unless` +unless true do +  "Вы этого никогда не увидите" +else +  "Вы увидите это" +end + +# Помните сопоставление с образцом? +# Многие конструкции в Elixir построены вокруг него. + +# `case` позволяет сравнить выражение с несколькими образцами: +case {:one, :two} do +  {:four, :five} -> +    "Этот образец не совпадёт" +  {:one, x} -> +    "Этот образец совпадёт и присвоит переменной `x` значение `:two`" +  _ -> +    "Этот образец совпадёт с чем угодно" +end + +# Символ `_` называется анонимной переменной. Используйте `_` для значений, +# которые в текущем выражении вас не интересуют. Например, вам интересна лишь +# голова списка, а хвост вы желаете проигнорировать: +[head | _] = [1,2,3] +head #=> 1 + +# Для лучшей читаемости вы можете написать: +[head | _tail] = [:a, :b, :c] +head #=> :a + +# `cond` позволяет проверить сразу несколько условий за раз. +# Используйте `cond` вместо множественных операторов `if`. +cond do +  1 + 1 == 3 -> +    "Вы меня никогда не увидите" +  2 * 5 == 12 -> +    "И меня" +  1 + 2 == 3 -> +    "Вы увидите меня" +end + +# Обычно последним условием идёт `true`, которое выполнится, если все предыдущие +# условия оказались ложны. +cond do +  1 + 1 == 3 -> +    "Вы меня никогда не увидите" +  2 * 5 == 12 -> +    "И меня" +  true -> +    "Вы увидите меня (по сути, это `else`)" +end + +# Обработка ошибок происходит в блоках `try/catch`. +# Elixir также поддерживает блок `after`, который выполнится в любом случае. +try do +  throw(:hello) +catch +  message -> "Поймана ошибка с сообщением #{message}." +after +  IO.puts("Я выполнюсь всегда") +end +#=> Я выполнюсь всегда +# "Поймана ошибка с сообщением hello." + +## --------------------------- +## -- Модули и функции +## --------------------------- + +# Анонимные функции (обратите внимание на точку при вызове функции) +square = fn(x) -> x * x end +square.(5) #=> 25 + +# Анонимные функции принимают клозы и гарды. +# +# Клозы (от англ. clause) — варианты исполнения функции.  +# +# Гарды (от англ. guard) — охранные выражения, уточняющие сопоставление с +# образцом в функциях. Гарды следуют после ключевого слова `when`. +f = fn +  x, y when x > 0 -> x + y +  x, y -> x * y +end + +f.(1, 3)  #=> 4 +f.(-1, 3) #=> -3 + +# В Elixir много встроенных функций. +# Они доступны в текущей области видимости. +is_number(10)    #=> true +is_list("hello") #=> false +elem({1,2,3}, 0) #=> 1 + +# Вы можете объединить несколько функций в модуль. Внутри модуля используйте `def`, +# чтобы определить свои функции. +defmodule Math do +  def sum(a, b) do +    a + b +  end + +  def square(x) do +    x * x +  end +end + +Math.sum(1, 2) #=> 3 +Math.square(3) #=> 9 + +# Чтобы скомпилировать модуль Math, сохраните его в файле `math.ex` +# и наберите в терминале: `elixirc math.ex` + +defmodule PrivateMath do +  # Публичные функции начинаются с `def` и доступны из других модулей. +  def sum(a, b) do +    do_sum(a, b) +  end + +  # Приватные функции начинаются с `defp` и доступны только внутри своего модуля. +  defp do_sum(a, b) do +    a + b +  end +end + +PrivateMath.sum(1, 2)    #=> 3 +PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError) + +# Функции внутри модуля тоже принимают клозы и гарды +defmodule Geometry do +  def area({:rectangle, w, h}) do +    w * h +  end + +  def area({:circle, r}) when is_number(r) do +    3.14 * r * r +  end +end + +Geometry.area({:rectangle, 2, 3})        #=> 6 +Geometry.area({:circle, 3})              #=> 28.25999999999999801048 +Geometry.area({:circle, "not_a_number"}) #=> ** (FunctionClauseError) + +# Из-за неизменяемых переменных в Elixir важную роль играет рекурсия +defmodule Recursion do +  def sum_list([head | tail], acc) do +    sum_list(tail, acc + head) +  end + +  def sum_list([], acc) do +    acc +  end +end + +Recursion.sum_list([1,2,3], 0) #=> 6 + +# Модули в Elixir поддерживают атрибуты. +# Атрибуты бывают как встроенные, так и ваши собственные. +defmodule MyMod do +  @moduledoc """ +  Это встроенный атрибут +  """ + +  @my_data 100 # А это ваш атрибут +  IO.inspect(@my_data) #=> 100 +end + +# Одна из фишек языка — оператор `|>` +# Он передаёт выражение слева в качестве первого аргумента функции справа: +Range.new(1,10) +|> Enum.map(fn x -> x * x end) +|> Enum.filter(fn x -> rem(x, 2) == 0 end) +#=> [4, 16, 36, 64, 100] + +## --------------------------- +## -- Структуры и исключения +## --------------------------- + +# Структуры — это расширения поверх карт, привносящие в Elixir значения по +# умолчанию, проверки на этапе компиляции и полиморфизм. +defmodule Person do +  defstruct name: nil, age: 0, height: 0 +end + +joe_info = %Person{ name: "Joe", age: 30, height: 180 } +#=> %Person{age: 30, height: 180, name: "Joe"} + +# Доступ к полю структуры +joe_info.name #=> "Joe" + +# Обновление поля структуры +older_joe_info = %{ joe_info | age: 31 } +#=> %Person{age: 31, height: 180, name: "Joe"} + +# Блок `try` с ключевым словом `rescue` используется для обработки исключений +try do +  raise "какая-то ошибка" +rescue +  RuntimeError -> "перехвачена ошибка рантайма" +  _error -> "перехват любой другой ошибки" +end +#=> "перехвачена ошибка рантайма" + +# У каждого исключения есть сообщение +try do +  raise "какая-то ошибка" +rescue +  x in [RuntimeError] -> +    x.message +end +#=> "какая-то ошибка" + +## --------------------------- +## -- Параллелизм +## --------------------------- + +# Параллелизм в Elixir построен на модели акторов. Для написания +# параллельной программы нам понадобятся три вещи: +# 1. Создание процессов +# 2. Отправка сообщений +# 3. Приём сообщений + +# Новый процесс создаётся функцией `spawn`, которая принимает функцию +# в качестве аргумента. +f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245> +spawn(f)            #=> #PID<0.40.0> + +# `spawn` возвращает идентификатор процесса (англ. process identifier, PID). +# Вы можете использовать PID для отправки сообщений этому процессу. Сообщения +# отправляются через оператор `send`. А для приёма сообщений используется +# механизм `receive`: + +# Блок `receive do` ждёт сообщений и обработает их, как только получит. Блок +# `receive do` обработает лишь одно полученное сообщение. Чтобы обработать +# несколько сообщений, функция, содержащая блок `receive do`, должна рекурсивно +# вызывать себя. + +defmodule Geometry do +  def area_loop do +    receive do +      {:rectangle, w, h} -> +        IO.puts("Площадь = #{w * h}") +        area_loop() +      {:circle, r} -> +        IO.puts("Площадь = #{3.14 * r * r}") +        area_loop() +    end +  end +end + +# Скомпилируйте модуль и создайте процесс +pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0> +# Альтернативно +pid = spawn(Geometry, :area_loop, []) + +# Отправьте сообщение процессу +send pid, {:rectangle, 2, 3} +#=> Площадь = 6 +#   {:rectangle,2,3} + +send pid, {:circle, 2} +#=> Площадь = 12.56 +#   {:circle,2} + +# Кстати, интерактивная консоль — это тоже процесс. +# Чтобы узнать текущий PID, воспользуйтесь встроенной функцией `self` +self() #=> #PID<0.27.0> + +## --------------------------- +## -- Агенты +## --------------------------- + +# Агент — это процесс, который следит за некоторым изменяющимся значением. + +# Создайте агента через `Agent.start_link`, передав ему функцию. +# Начальным состоянием агента будет значение, которое эта функция возвращает. +{ok, my_agent} = Agent.start_link(fn -> ["красный", "зелёный"] end) + +# `Agent.get` принимает имя агента и анонимную функцию `fn`, которой будет +# передано текущее состояние агента. В результате вы получите то, что вернёт +# анонимная функция. +Agent.get(my_agent, fn colors -> colors end) #=> ["красный", "зелёный"] + +# Похожим образом вы можете обновить состояние агента +Agent.update(my_agent, fn colors -> ["синий" | colors] end) +``` + +## Ссылки + +* [Официальный сайт](http://elixir-lang.org) +* [Шпаргалка по языку](http://media.pragprog.com/titles/elixir/ElixirCheat.pdf) +* [Книга "Programming Elixir"](https://pragprog.com/book/elixir/programming-elixir) +* [Книга "Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) +* [Книга "Programming Erlang: Software for a Concurrent World"](https://pragprog.com/book/jaerlang2/programming-erlang) diff --git a/ru-ru/go-ru.html.markdown b/ru-ru/go-ru.html.markdown index 6c8622cc..37592258 100644 --- a/ru-ru/go-ru.html.markdown +++ b/ru-ru/go-ru.html.markdown @@ -35,7 +35,7 @@ package main  // Import предназначен для указания зависимостей этого файла.  import (      "fmt"      // Пакет в стандартной библиотеке Go -    "io/ioutil" // Реализация функций ввод/ввывода. +    "io/ioutil" // Реализация функций ввод/вывода.      "net/http" // Да, это веб-сервер!      "strconv"  // Конвертирование типов в строки и обратно      m "math"   // Импортировать math под локальным именем m. @@ -270,7 +270,7 @@ func learnErrorHandling() {  // c – это тип данных channel (канал), объект для конкурентного взаимодействия.  func inc(i int, c chan int) { -    c <- i + 1 // когда channel слева, <- являтся оператором "отправки". +    c <- i + 1 // когда channel слева, <- является оператором "отправки".  }  // Будем использовать функцию inc для конкурентной инкрементации чисел. diff --git a/ru-ru/haml-ru.html.markdown b/ru-ru/haml-ru.html.markdown new file mode 100644 index 00000000..c2f8852e --- /dev/null +++ b/ru-ru/haml-ru.html.markdown @@ -0,0 +1,233 @@ +--- +language: haml +filename: learnhaml-ru.haml +contributors: +    - ["Simon Neveu", "https://github.com/sneveu"] +    - ["Vasiliy Petrov", "https://github.com/Saugardas"] +translators: +    - ["Vasiliy Petrov", "https://github.com/Saugardas"] +lang: ru-ru +--- + +Haml - язык разметки (в основном используемый с Ruby), с помощью которого могут быть легко описаны HTML-документы. +Он является популярной альтернативой используемому в Rails шаблонизатору (.erb), и позволяет вставлять Ruby-код в вашу разметку. + +Haml убирает избыточность закрывающих тегов благодаря отступам. +В результате получается меньшая по размерам, хорошо структурированная, логичная и читаемая разметка. + +Вы можете использовать Haml и вне Ruby-проекта. Установите гем Haml и используйте командную строку для конвертирования html-файлов: + +```shell +$ haml input_file.haml output_file.html +``` + + +```haml +/ ------------------------------------------- +/ Отступы +/ ------------------------------------------- + +/ +  Отступы являются важным элементом синтаксиса, поэтому они должны быть +  одинаковыми во всём документе. Обычно используют два пробела, +  но это не является обязательным правилом - можно использовать любое +  количество пробелов для отступов. Главное, чтобы это количество было +  одинаковым во всём документе. + + +/ ------------------------------------------- +/ Комментарии +/ ------------------------------------------- + +/ Комментари начинается с символа косой черты. + +/ +  Для написания многострочного комментария расположите ваш комментарий +  на следующем уровне вложенности от символа косой черты + +-# "Скрытый" комментарий. Этот комментарий не попадёт в результирующий документ + + +/ ------------------------------------------- +/ Элементы HTML +/ ------------------------------------------- + +/ Чтобы написать тег, используйте символ процента (%) и название тега +%body +  %header +    %nav + +/ Обратите внимание на отсутствие закрывающих тегов. Код выше выведет: +  <body> +    <header> +      <nav></nav> +    </header> +  </body> + +/ +  Так как тег div используется очень часто, его можно опустить. +  Можно указать только имя класса или идентификатора (. или #) +  Например код: + +%div.my_class +  %div#my_id + +/ Можно записать: +.my_class +  #my_id + +/ Для добавления контента в тег, просто добавьте текст после объявления тега +%h1 Заголовок + +/ Для многострочного содержания используйте отступы +%p +  Многострочное содержание +  в две строки. + +/ +  Амперсанд - равно (&=) обрабатывают Ruby код также, как и без амперсанда, +  но HTML-символы в результате будут экранированы. Например: + +%p +  &= "Да & да" + +/ выведет 'Да & да' + +/ +  Чтобы выполнять Ruby-код без экранрования, можно использовать +  "восклицательный знак" и "равно" (!=) + +%p +  != "Тег абзаца <p></p>" + +/ выведет 'Тег абзаца <p></p>' + +/ CSS - классы могут быть добавлены через точку от определения тега +%div.foo.bar + +/ Или с помощью хеша атрибутов +%div{ :class => 'foo bar' } + +/ Хеш атрибутов может быть добавлен для любого тега +%a{ :href => '#', :class => 'bar', :title => 'Bar' } + +/ Для булевых атрибутов просто присвойте значение 'true' +%input{ :selected => true } + +/ Для data - атрибутов присвойте ключу :data хеш с данными +%div{ :data => { :attribute => 'foo' } } + +/ Для Ruby версии 1.9 или выше, можно использовать новый синтаксис хешей +%div{ data: { attribute: 'foo' } } + +/ Также можно использовать HTML-синтаксис атрибутов +%a(href='#' title='bar') + +/ Можно использовать оба варианта одновременно +%a(href='#'){ title: @my_class.title } + + +/ ------------------------------------------- +/ Включение Ruby +/ ------------------------------------------- + +/ Для включения Ruby кода используйте знак "равно" + +%h1= book.name + +%p +  = book.author +  = book.publisher + + +/ Для выполнения Ruby кода без вывода в HTML, используйте знак дефиса +- books = ['book 1', 'book 2', 'book 3'] + +/ +  Можно выполнять любой Ruby код, например с блоками. +  Закрывающий "end" не нужен, так как они будут закрыты автоматически, +  основываясь на вложенности. + +- books.shuffle.each_with_index do |book, index| +  %h1= book + +  - if book do +    %p This is a book +     +/ Добавление списка +%ul +  %li +    =item1 +    =item2 + +/ ------------------------------------------- +/ Пример таблицы с классами Bootstrap'a +/ ------------------------------------------- + +%table.table.table-hover +  %thead +    %tr +      %th Header 1 +      %th Header 2 +     +    %tr +      %td Value1 +      %td value2 +     +  %tfoot +    %tr +      %td +        Foot value + + +/ ------------------------------------------- +/ Интерполяция Ruby кода +/ ------------------------------------------- + +/ Ruby код может быть интерполирован в текст с помощью #{} +%p Ваша самая любимая игра - #{best_game} + +/ Тоже самое, что и: +%p= "Ваша самая любимая игра - #{best_game}" + + +/ ------------------------------------------- +/ Фильтры +/ ------------------------------------------- + +/ +  Фильтры передают связанный блок текста в соотвествующую +  фильтрующую программу и возвращают результат в Haml +  Фильтр обозначается двоеточием и названием фильтра: + +/ Markdown filter +:markdown +  # Заголовк + +  Текст **внутри** *блока* + +/ Код выше будет скомпилирован в +<h1>Заголовок</h1> + +<p>Текст <strong>внутри</strong> <em>блока</em></p> + +/ Javascript - фильтр +:javascript +  console.log('This is inline <script>'); + +/ скомпилируется в: +<script> +  console.log('This is inline <script>'); +</script> + +/ +  Существует множество типов фильров (:markdown, :javascript, :coffee, +  :css, :ruby и так далее). Вы можете определить собственный фильтр c +  помощью Haml::Filters. + +``` + +## Дополнительные ресурсы + +- [О Haml](https://haml.ru) - Хорошее введение, описывает преимущества Haml. +- [Документация](https://haml.ru/documentation/) - Документация Haml на русском языке. diff --git a/ru-ru/haskell-ru.html.markdown b/ru-ru/haskell-ru.html.markdown index e15fe6b7..b1b8eb79 100644 --- a/ru-ru/haskell-ru.html.markdown +++ b/ru-ru/haskell-ru.html.markdown @@ -1,5 +1,6 @@  ---  language: Haskell +filename: haskell-ru.hs  contributors:      - ["Adit Bhargava", "http://adit.io"]  translators: @@ -66,7 +67,7 @@ not False -- True  ---------------------------------------------------- --- Списки и Кортежи +-- 2. Списки и Кортежи  ----------------------------------------------------  -- Все элементы списка в Haskell diff --git a/ru-ru/html-ru.html.markdown b/ru-ru/html-ru.html.markdown index 5cf95fc4..120981b9 100644 --- a/ru-ru/html-ru.html.markdown +++ b/ru-ru/html-ru.html.markdown @@ -1,10 +1,11 @@  ---  language: html -filename: learnhtml.html +filename: learnhtml-ru.html  contributors:      - ["Christophe THOMAS", "https://github.com/WinChris"]  translators:      - ["Lana Tim", "https://github.com/LanaTim"] +lang: ru-ru  ---  HTML расшифровывается как Hypertext Markup Language(гипертекстовый язык разметки). diff --git a/ru-ru/java-ru.html.markdown b/ru-ru/java-ru.html.markdown index a1a5cdfc..1aff801c 100644 --- a/ru-ru/java-ru.html.markdown +++ b/ru-ru/java-ru.html.markdown @@ -1,12 +1,13 @@  ---  language: java +filename: LearnJava-ru.java  contributors:      - ["Jake Prather", "http://github.com/JakeHP"]      - ["Madison Dickson", "http://github.com/mix3d"]  translators:      - ["Sergey Gaykov", "https://github.com/gaykov"] -filename: LearnJavaRu.java  lang: ru-ru +  ---  Java - это объектно-ориентированный язык программирования общего назначения, diff --git a/ru-ru/javascript-ru.html.markdown b/ru-ru/javascript-ru.html.markdown index 1f1ffce6..c31c6994 100644 --- a/ru-ru/javascript-ru.html.markdown +++ b/ru-ru/javascript-ru.html.markdown @@ -1,7 +1,7 @@  ---  language: javascript  contributors: -    - ["Adam Brenecki", "http://adam.brenecki.id.au"] +    - ["Leigh Brenecki", "https://leigh.net.au"]      - ["Ariel Krakowski", "http://www.learneroo.com"]  filename: javascript-ru.js  translators: @@ -420,7 +420,7 @@ myObj.__proto__ = myPrototype;  myObj.meaningOfLife; // = 42  // Для функций это тоже работает. -myObj.myFunc(); // = "Привет, мир!" +myObj.myFunc(); // = "привет, мир!"  // Если интерпретатор не найдёт свойство в прототипе, то продожит поиск  // в прототипе прототипа и так далее. 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 new file mode 100644 index 00000000..85f44c96 --- /dev/null +++ b/ru-ru/kotlin-ru.html.markdown @@ -0,0 +1,375 @@ +--- +language: kotlin +filename: LearnKotlin-ru.kt +lang: ru-ru +contributors: +    - ["S Webber", "https://github.com/s-webber"] +translators: +    - ["Vadim Toptunov", "https://github.com/VadimToptunov"] +--- + +Kotlin - статически типизированный язык для JVM, Android и браузера. Язык полностью совместим c Java.  +[Более детальная информация здесь.](https://kotlinlang.org/) + +```kotlin +// Однострочные комментарии начинаются с // +/* +А вот так выглядят многострочные комментарии. +*/ + +// Ключевое слово "package" действует и используется // абсолютно также, как и в Java. +package com.learnxinyminutes.kotlin + +/* +Точкой входа в программу на языке Kotlin является функция "main". +Приведенная ниже функция передает массив, содержащий любые аргументы из командной строки. +*/ +fun main(args: Array<String>) { +    /* +    Объявление значений производится с помощью или "var", или "val". +    Значения объявленные с помощью "val" не могут быть изменены или перезаписаны, в то время как объявленные с помощью "var" - могут. +    */ +    val fooVal = 10 // мы не можем потом изменить значение fooVal на какое-либо иное +    var fooVar = 10 +    fooVar = 20 // значение fooVar затем может быть изменено. + +    /* +    В большинстве случаев Kotlin самостоятельно может определить тип переменной, поэтому нам не нужно явно указывать его каждый раз. +    Мы можем явно объявить тип переменной следующим образом: +    */ +    val foo: Int = 7 + +    /* +    Строки могут быть представлены тем же образом, что и в Java. +    Для экранирования используется обратный слэш. +    */ +    val fooString = "My String Is Here!" +    val barString = "Printing on a new line?\nNo Problem!" +    val bazString = "Do you want to add a tab?\tNo Problem!" +    println(fooString) +    println(barString) +    println(bazString) + +    /* +    Необработанная строка разделяется тройной кавычкой ("""). +    Необработанные строки могут содержать символы новой строки и любые другие символы. +    */ +    val fooRawString = """ +fun helloWorld(val name : String) { +   println("Hello, world!") +} +""" +    println(fooRawString) + +    /* +    Строки могут содержать в себе шаблонные выражения. +    Шаблонные выражения начинаются со знака доллара ($). +    */ +    val fooTemplateString = "$fooString has ${fooString.length} characters" +    println(fooTemplateString) + +    /* +    Переменная, которая содержит null должна быть явно обозначена как nullable. +    Переменная может быть обозначена как nullable с помощью добавления знака вопроса(?) к ее типу. +    Мы можем получить доступ к nullable переменной используя оператор ?. . +    Для того, чтобы указать иное значение, если переменная является null, мы используем оператор ?: . +    */ +    var fooNullable: String? = "abc" +    println(fooNullable?.length) // => 3 +    println(fooNullable?.length ?: -1) // => 3 +    fooNullable = null +    println(fooNullable?.length) // => null +    println(fooNullable?.length ?: -1) // => -1 + +    /* +    Функции могут быть объявлены с помощью ключевого слова "fun". +    Аргументы функции указываются в скобках после имени функции. +    Аргументы функции также могу иметь и значение по умолчанию. +    Если требуется, то тип возвращаемого функцией значения, может быть указан после аргументов. +    */ +    fun hello(name: String = "world"): String { +        return "Hello, $name!" +    } +    println(hello("foo")) // => Hello, foo! +    println(hello(name = "bar")) // => Hello, bar! +    println(hello()) // => Hello, world! + +    /* +    Параметр функции может быть отмечен с помощью ключевого слова "vararg", для того чтобы позволить аргументам попасть в функцию. +    */ +    fun varargExample(vararg names: Int) { +        println("Argument has ${names.size} elements") +    } +    varargExample() // => Argument has 0 elements +    varargExample(1) // => Argument has 1 elements +    varargExample(1, 2, 3) // => Argument has 3 elements + +    /* +    Если функция состоит из одиночного выражения, фигурные скобки могут быть опущены. Тело функции указывается после знака = . +    */ +    fun odd(x: Int): Boolean = x % 2 == 1 +    println(odd(6)) // => false +    println(odd(7)) // => true + +    // Если возвращаемый тип может быть выведен, то нам не нужно его дополнительно указывать. +    fun even(x: Int) = x % 2 == 0 +    println(even(6)) // => true +    println(even(7)) // => false + +    // Функции могут брать другие функции в качестве аргументов, а также могут возвращать функции.  +    fun not(f: (Int) -> Boolean): (Int) -> Boolean { +        return {n -> !f.invoke(n)} +    } +    // Именованные функции могут быть определены в качестве аргументов с помощью оператора :: . +    val notOdd = not(::odd) +    val notEven = not(::even) +    // Lambda-выражения могут быть определены в качестве аргументов. +    val notZero = not {n -> n == 0} +    /* +    Если lambda-выражение имеет только один параметр, то ее определение может быть опущено (вместе с ->). +    Имя этого единственного параметра будет "it". +    */ +    val notPositive = not {it > 0} +    for (i in 0..4) { +        println("${notOdd(i)} ${notEven(i)} ${notZero(i)} ${notPositive(i)}") +    } + +    // Ключевое слово "class" используется для  +    // объявления классов. +    class ExampleClass(val x: Int) { +        fun memberFunction(y: Int): Int { +            return x + y +        } + +        infix fun infixMemberFunction(y: Int): Int { +            return x * y +        } +    } +    /* +    Чтобы создать новый экземпляр класса, нужно вызвать конструктор. +    Обратите внимание, что в Kotlin нет ключевого слова "new". +    */ +    val fooExampleClass = ExampleClass(7) +    // Функции-члены могут быть вызваны с использованием точечной нотации. +    println(fooExampleClass.memberFunction(4)) // => 11 +    /* +    В случае, если функция была помечена ключевым словом "infix", она может быть вызвана с помощью инфиксной нотации.  +    */ +    println(fooExampleClass infixMemberFunction 4) // => 28 + +    /* +    Data-классы - это компактный способ создать классы, которые лишь хранят данные. +    Методы "hashCode"/"equals" и "toString" генерируютсяч автоматически.  +    */ +    data class DataClassExample (val x: Int, val y: Int, val z: Int) +    val fooData = DataClassExample(1, 2, 4) +    println(fooData) // => DataClassExample(x=1, y=2, z=4) + +    // Data-классы обладают функцией "copy". +    val fooCopy = fooData.copy(y = 100) +    println(fooCopy) // => DataClassExample(x=1, y=100, z=4) + +    // Объекты могут быть деструктурированы на множество переменных. +    val (a, b, c) = fooCopy +    println("$a $b $c") // => 1 100 4 +     +    // Деструктурирование в цикле "for" +    for ((a, b, c) in listOf(fooData)) { +        println("$a $b $c") // => 1 100 4 +    } +     +    val mapData = mapOf("a" to 1, "b" to 2) +    // Map.Entry также может быть дествуктурирован +    for ((key, value) in mapData) { +        println("$key -> $value") +    } + +    // Функция "with" аналогична оператору "with" в JavaScript. +    data class MutableDataClassExample (var x: Int, var y: Int, var z: Int) +    val fooMutableData = MutableDataClassExample(7, 4, 9) +    with (fooMutableData) { +        x -= 2 +        y += 2 +        z-- +    } +    println(fooMutableData) // => MutableDataClassExample(x=5, y=6, z=8) + +    /* +    Можно создать список с помощью функции "ListOf". +    Этот список будет неизменяемым, т.е. элементы не могут быть удалены или добавлены в него. +    */ +    val fooList = listOf("a", "b", "c") +    println(fooList.size) // => 3 +    println(fooList.first()) // => a +    println(fooList.last()) // => c +    // Элементы списка доступны по их индексу в нем.  +    println(fooList[1]) // => b + +    // Изменяемый список может быть создан спомощью функции "mutableListOf". +    val fooMutableList = mutableListOf("a", "b", "c") +    fooMutableList.add("d") +    println(fooMutableList.last()) // => d +    println(fooMutableList.size) // => 4 + +    // Мы можем создать набор, используя функцию "setOf".  +    val fooSet = setOf("a", "b", "c") +    println(fooSet.contains("a")) // => true +    println(fooSet.contains("z")) // => false + +    // Мы можем создать отображение (map), используя функцию "mapOf". +    val fooMap = mapOf("a" to 8, "b" to 7, "c" to 9) +    // Получить доступ к значениям отображения (map) можно с помощью их ключа.  +    println(fooMap["a"]) // => 8 + +    /* +    Последовательности представляют собой коллекции с ленивой оценкой. +    Мы можем создать последовательность, используя функцию "generateSequence". +    */ +    val fooSequence = generateSequence(1, { it + 1 }) +    val x = fooSequence.take(10).toList() +    println(x) // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + +    // Пример использования последовательности для генерации чисел Фибоначчи: +    fun fibonacciSequence(): Sequence<Long> { +        var a = 0L +        var b = 1L + +        fun next(): Long { +            val result = a + b +            a = b +            b = result +            return a +        } + +        return generateSequence(::next) +    } +    val y = fibonacciSequence().take(10).toList() +    println(y) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + +    // Kotlin предоставляет функции высшего порядка для работы с коллекциями. +    val z = (1..9).map {it * 3} +                  .filter {it < 20} +                  .groupBy {it % 2 == 0} +                  .mapKeys {if (it.key) "even" else "odd"} +    println(z) // => {odd=[3, 9, 15], even=[6, 12, 18]} + +    // Цикл "for" может использоваться со всем, что предоставляет  итератор. +    for (c in "hello") { +        println(c) +    } + +    // Циклы "while" работают также, как и в других языках. +    var ctr = 0 +    while (ctr < 5) { +        println(ctr) +        ctr++ +    } +    do { +        println(ctr) +        ctr++ +    } while (ctr < 10) + +    /* +    "if" может быть использован в качестве выражения, которое возвращает значение. +    По этой причине в Kotlin тернарный оператор ?: не нужен. +    */ +    val num = 5 +    val message = if (num % 2 == 0) "even" else "odd" +    println("$num is $message") // => 5 is odd + +    // "when" может быть использован как альтернатива цепочке "if-else if". +    val i = 10 +    when { +        i < 7 -> println("first block") +        fooString.startsWith("hello") -> println("second block") +        else -> println("else block") +    } + +    // "when" может быть использован с аргументами. +    when (i) { +        0, 21 -> println("0 or 21") +        in 1..20 -> println("in the range 1 to 20") +        else -> println("none of the above") +    } + +    // "when" также может быть использовано как функция, возвращающая значение. +    var result = when (i) { +        0, 21 -> "0 or 21" +        in 1..20 -> "in the range 1 to 20" +        else -> "none of the above" +    } +    println(result) + +    /* +    Мы можем проверить, что объект принадлежит к определенному типу, используя оператор "is". +    Если объект проходит проверку типа, то он может использоваться как этот тип без явной его  передачи. +    */ +    fun smartCastExample(x: Any) : Boolean { +        if (x is Boolean) { +            // x is automatically cast to Boolean +            return x +        } else if (x is Int) { +            // x is automatically cast to Int +            return x > 0 +        } else if (x is String) { +            // x is automatically cast to String +            return x.isNotEmpty() +        } else { +            return false +        } +    } +    println(smartCastExample("Hello, world!")) // => true +    println(smartCastExample("")) // => false +    println(smartCastExample(5)) // => true +    println(smartCastExample(0)) // => false +    println(smartCastExample(true)) // => true + +    // Smartcast также работает с блоком "when" +    fun smartCastWhenExample(x: Any) = when (x) { +        is Boolean -> x +        is Int -> x > 0 +        is String -> x.isNotEmpty() +        else -> false +    } + +    /* +    Расширения - это способ добавить новый функционал к классу.  +    Это то же самое, что методы расширений в C#. +    */ +    fun String.remove(c: Char): String { +        return this.filter {it != c} +    } +    println("Hello, world!".remove('l')) // => Heo, word! + +    println(EnumExample.A) // => A +    println(ObjectExample.hello()) // => hello +} + +// Enum-классы схожи с типами enum в Java. +enum class EnumExample { +    A, B, C +} + +/* +Ключевое слово "object" может использоваться для создания одноэлементных объектов. +Мы не можем его инстанцировать, но можем вызывать его уникальный экземпляр по имени. +Это похоже на одиночные объекты Scala. +*/ +object ObjectExample { +    fun hello(): String { +        return "hello" +    } +} + +fun useObject() { +    ObjectExample.hello() +    val someRef: Any = ObjectExample // we use objects name just as is +} + +``` + +### Дальнейшее чтение: + +* [Учебные материалы по Kotlin](https://kotlinlang.org/docs/tutorials/) +* [Попробуй Kotlin в своем браузере](http://try.kotlinlang.org/) +* [Список ресурсов по языку Kotlin](http://kotlin.link/) diff --git a/ru-ru/learnvisualbasic-ru.html.markdown b/ru-ru/learnvisualbasic-ru.html.markdown new file mode 100644 index 00000000..72e1358c --- /dev/null +++ b/ru-ru/learnvisualbasic-ru.html.markdown @@ -0,0 +1,284 @@ +--- +language: Visual Basic +contributors: +    - ["Brian Martin", "http://brianmartin.biz"] +translators: +    - ["satory-ra", "https://github.com/satory-ra"] +filename: learnvisualbasic-ru.vb +lang: ru-ru +--- + +```vbnet +Module Module1 + +    Sub Main() +        'Краткий обзор консольных приложений Visual Basic перед более +        'глубоким изучением. +        'Апостроф начинает строку комментария. +        'Чтобы изучить это руководство в компиляторе Visual Basic, +        'я создал систему навигации. +        'Эта система будет объяснена при прохождении этого урока. +        'Постепенно вы всё поймете. +        Console.Title = ("Выучи Х за Y минут") +        Console.WriteLine("НАВИГАЦИЯ") 'Display +        Console.WriteLine("") +        Console.ForegroundColor = ConsoleColor.Green +        Console.WriteLine("1. Вывод данных") +        Console.WriteLine("2. Ввод данных") +        Console.WriteLine("3. Расчёт целых чисел") +        Console.WriteLine("4. Расчёт десятичных дробей") +        Console.WriteLine("5. Калькулятор") +        Console.WriteLine("6. Использование циклов Do While") +        Console.WriteLine("7. Использование циклов For") +        Console.WriteLine("8. Условные выражения") +        Console.WriteLine("9. Выберите напиток") +        Console.WriteLine("50. О приложении") +        Console.WriteLine("Выберите номер из списка") +        Dim selection As String = Console.ReadLine +        '«Case» в операторе Select не является обязательным. +        'Например, "Select selection" вместо "Select Case selection" +        'также будет работать. +        Select Case selection +            Case "1" 'Вывод данных +                Console.Clear() 'Очищает окно консоли +                HelloWorldOutput() 'Открывает приватную подпрограмму. +            Case "2" 'Ввод данных +                Console.Clear() +                HelloWorldInput() +            Case "3" 'Расчёт целых чисел +                Console.Clear() +                CalculatingWholeNumbers() +            Case "4" 'Расчёт десятичных дробей +                Console.Clear() +                CalculatingDecimalNumbers() +            Case "5" 'Калькулятор +                Console.Clear() +                WorkingCalculator() +            Case "6" 'Использование циклов Do While +                Console.Clear() +                UsingDoWhileLoops() +            Case "7" 'Использование циклов For +                Console.Clear() +                UsingForLoops() +            Case "8" 'Условные выражения +                Console.Clear() +                ConditionalStatement() +            Case "9" 'Выражения If/Else +                Console.Clear() +                IfElseStatement() 'Выберите напиток +            Case "50" 'Окно сообщения «О приложении» +                Console.Clear() +                Console.Title = ("Выучи Х за Y минут :: О приложении") +                MsgBox("Это руководство от Брайана Мартина (@BrianMartinn") +                Console.Clear() +                Main() +                Console.ReadLine() + +        End Select +    End Sub + +    'Один - Я использую эти цифры для того, чтобы было проще +    'соотносить код с системой навигации. + +    'Мы используем частные подпрограммы для разделения различных +    'разделов программы. +    Private Sub HelloWorldOutput() +        'Название консольного приложения +        Console.Title = "Вывод данных | Выучи Х за Y минут" +        'Используйте Console.Write ("") или Console.WriteLine ("") +        'для отображения результатов. +        'Затем следует Console.Read () или Console.Readline () +        'Console.ReadLine () показывает вывод в консоли. +        Console.WriteLine("Hello World") +        Console.ReadLine() +    End Sub + +    'Два +    Private Sub HelloWorldInput() +        Console.Title = "Ввод данных | Выучи Х за Y минут" +        'Переменная +        'используется для хранения пользовательских данных. +        'Объявление переменных начинается с Dim и заканчиваются +        'As VariableType (тип переменной). + +        'В этом уроке мы хотим узнать ваше имя и заставить программу  +        'реагировать на это. +        Dim username As String +        'Мы используем тип «string», так как ваше имя - это текстовая переменная. +        Console.WriteLine("Привет, как тебя зовут? ") 'Просит ввести имя. +        username = Console.ReadLine() 'Сохраняет имя в переменной username. +        Console.WriteLine("Пирвет, " + username) 'Выводит: «Привет, 'имя'» +        Console.ReadLine() 'Отображает вышеуказанный вывод. + +        'Вышеуказанная программа спросит ваше имя и скажет вам привет. +        'Есть и другие типы переменных, такие как целые числа (Integer), +        'мы используем Integer для обработки целых чисел. +    End Sub + +    'Три +    Private Sub CalculatingWholeNumbers() +        Console.Title = "Расчёт целых чисел | Выучи Х за Y минут" +        Console.Write("Первое число: ") 'Введите первое целое число: 1, 2, 50, 104 и т.д. +        Dim a As Integer = Console.ReadLine() +        Console.Write("Второе число: ") 'Введите второе целое число. +        Dim b As Integer = Console.ReadLine() +        Dim c As Integer = a + b +        Console.WriteLine(c) +        Console.ReadLine() +        'Приведенная программа сумирует два целых числа +    End Sub + +    'Четыре +    Private Sub CalculatingDecimalNumbers() +        Console.Title = "Расчёт десятичных дробей | Выучи Х за Y минут" +        'Мы также должны уметь обрабатывать десятичные дроби. +        'Просто измените тип переменной с Integer на Double. + +        'Введите число с плавающей точкой: 1.2, 2.4, 50.1, 104.9 и т.д. +        Console.Write("Первое число: ") +        Dim a As Double = Console.ReadLine +        Console.Write("Второе число: ") 'Введите второе число с плавающей точкой. +        Dim b As Double = Console.ReadLine +        Dim c As Double = a + b +        Console.WriteLine(c) +        Console.ReadLine() +        'Приведенный выше код может сложить две десятичных дроби. +    End Sub + +    'Пять +    Private Sub WorkingCalculator() +        Console.Title = "Калькулятор | Выучи Х за Y минут" +        'Но что, если вам нужен калькулятор, который может обрабатывать сложение,  +        'вычитание, умножение и деление? +        'Просто скопируйте и вставьте приведенный код. +        Console.Write("Первое число: ") +        Dim a As Double = Console.ReadLine +        Console.Write("Второе число: ") +        Dim b As Double = Console.ReadLine +        Dim c As Double = a + b +        Dim d As Double = a * b +        Dim e As Double = a - b +        Dim f As Double = a / b + +        'С помощью следующего кода мы можем вывести результат сложения, +        'вычитания, умножения и деления, рассчитанный выше, на экран. +        Console.Write(a.ToString() + " + " + b.ToString()) +        'Мы хотим, чтобы в начале ответа было 3 пробела, для этого  +        'вы можете использовать метод String.PadLeft (3). +        Console.WriteLine(" = " + c.ToString.PadLeft(3)) +        Console.Write(a.ToString() + " * " + b.ToString()) +        Console.WriteLine(" = " + d.ToString.PadLeft(3)) +        Console.Write(a.ToString() + " - " + b.ToString()) +        Console.WriteLine(" = " + e.ToString.PadLeft(3)) +        Console.Write(a.ToString() + " / " + b.ToString()) +        Console.WriteLine(" = " + f.ToString.PadLeft(3)) +        Console.ReadLine() + +    End Sub + +    'Шесть +    Private Sub UsingDoWhileLoops() +        'Код такой же, как и в предидущей подпрограмме +        'На этот раз мы спрашиваем, хочет ли пользователь продолжить (да или нет?) +        'Мы будем использовать цикл Do While, потому что не знаем, +        'понадобиться ли пользователю калькулятор болше одного раза. +        Console.Title = "Использование циклов Do While | Выучи Х за Y минут" +        Dim answer As String +        'Мы используем тип переменной "String", так как её значение текст. +        Do 'Мы начаем программу с +            Console.Write("Первое число: ") +            Dim a As Double = Console.ReadLine +            Console.Write("Второе число: ") +            Dim b As Double = Console.ReadLine +            Dim c As Double = a + b +            Dim d As Double = a * b +            Dim e As Double = a - b +            Dim f As Double = a / b + +            Console.Write(a.ToString() + " + " + b.ToString()) +            Console.WriteLine(" = " + c.ToString.PadLeft(3)) +            Console.Write(a.ToString() + " * " + b.ToString()) +            Console.WriteLine(" = " + d.ToString.PadLeft(3)) +            Console.Write(a.ToString() + " - " + b.ToString()) +            Console.WriteLine(" = " + e.ToString.PadLeft(3)) +            Console.Write(a.ToString() + " / " + b.ToString()) +            Console.WriteLine(" = " + f.ToString.PadLeft(3)) +            Console.ReadLine() +            'Спросите пользователя, хочет ли он продолжить, +            'в ответе учитывается регистр букв. +            Console.Write("Желаете ли вы продолжить? (да / нет)") +            'Программа берет значение и записывает в переменную answer. +            answer = Console.ReadLine() +            'Когда пользователь вводит «да», программа переходит к Do и снова запускается. +        Loop While answer = "yes" + +    End Sub + +    'Семь +    Private Sub UsingForLoops() +        'Иногда программу нужно запускать только один раз. +        'В этой программе мы осуществим обратный отсчет от 10. + +        Console.Title = "Использование циклов For | Выучи Х за Y минут" +        'Объявите переменные и Step (размер шага, то есть скорость уменьшения, +        'например, -1, -2, -3 и т.д.). +        For i As Integer = 10 To 0 Step -1 +            Console.WriteLine(i.ToString) 'Показывает значение счетчика. +        Next i 'Рассчитать новое значение i. +        Console.WriteLine("Поехали") +        Console.ReadLine() +    End Sub + +    'Восемь +    Private Sub ConditionalStatement() +        Console.Title = "Условные выражения | Выучи Х за Y минут" +        Dim userName As String +        Console.WriteLine("Привет, как тебя зовут? ") 'Спросите имя пользователя. +        userName = Console.ReadLine() 'Записать имя в переменную userName. +        If userName = "Адам" Then +            Console.WriteLine("Привет, Адам") +            Console.WriteLine("Спасибо за создание этого полезного сайта") +            Console.ReadLine() +        Else +            Console.WriteLine("Привет " + userName) +            Console.WriteLine("Вы заглянули на сайт www.learnxinyminutes.com") +            Console.ReadLine() 'Программа останавливается и выводит вышеуказанный текст. +        End If +    End Sub + +    'Девять +    Private Sub IfElseStatement() +        Console.Title = "Выражения If/Else | Выучи Х за Y минут" +        'Иногда важно рассмотреть более двух альтернатив. +        'Иногда некоторые из них лучше других. +        'Когда это произойдет, нам потребуется более одного утверждения «if» (если). +        'Оператор «if» подобен торговому автомату. +        'В котором пользователь пишет код (A1, A2, A3 и т.д.), чтобы выбрать элементы. +        'Все варианты могут быть объединены в одном утверждении «if». + +        Dim selection As String 'Объявить переменную для выбора +        Console.WriteLine("Пожалуйста, выберите продукт из нашего прекрасного торгового автомата.") +        Console.WriteLine("A1. для 7Up") +        Console.WriteLine("A2. для Fanta") +        Console.WriteLine("A3. для Dr. Pepper") +        Console.WriteLine("A4. для Diet Coke") + +        selection = Console.ReadLine() 'Сохранить выбор пользователя +        If selection = "A1" Then +            Console.WriteLine("7up") +        ElseIf selection = "A2" Then +            Console.WriteLine("Fanta") +        ElseIf selection = "A3" Then +            Console.WriteLine("Dr. Pepper") +        ElseIf selection = "A4" Then +            Console.WriteLine("Diet Coke") +        Else +            Console.WriteLine("Извините, у меня нет " + selection) +        End If +        Console.ReadLine() + +    End Sub + +End Module + +``` diff --git a/ru-ru/linker-ru.html.markdown b/ru-ru/linker-ru.html.markdown new file mode 100644 index 00000000..7df29c23 --- /dev/null +++ b/ru-ru/linker-ru.html.markdown @@ -0,0 +1,203 @@ +--- +category: tool +tool: linker +contributors: +    - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"] +translators: +    - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"] +lang: ru-ru +--- + +# Основные понятия и определения +**Счетчик позиций** - у компоновщика есть специальная переменная  +"." (точка) всегда содержит текущую позицию вывода. + +# Функции +**ADDR(section)** -  возвращает абсолютный адрес указанной секции. Однако  +данная секция должна быть определенна до использования функции ADDR. + +**ALIGN(exp)** -  возвращает значение счетчика позиций, выравненное на границу  +следующего за exp выражения. + +**SIZEOF(section)** -  возвращает размер секции в байтах. + +**FILL(param)** -  определяет образец заполнения для текущей секции. Все  +остальные неуказанные регионы внутри секции заполняются значением указанными  +в аргументе функции. + +**KEEP(param)** -  используется чтобы помечать param как неустранимый. + +**ENTRY(func)** -  определяет функцию, которая будет являться точкой входа  +в программу. + +```bash +# Определяем точку входа в программу +ENTRY(Reset_Handler) + +# Определяем перемнную которая содержит адрес вершины стека +_estack = 0x20020000;   +# Определяем перемнную которая содержит значение размера кучи   +_Min_Heap_Size = 0x200; +# Определяем перемнную которая содержит значение размера стека +_Min_Stack_Size = 0x400;  + +# Описание карты памяти доступной для данного процессора +# MEMORY +# { +# ИМЯ_ОБЛАСТИ_ПАМЯТИ	(права доступа)	: ORIGIN = АДРЕС_НАЧАЛА, LENGTH = РАЗМЕР +# } +# В нашем примере контроллер содержит три области памяти: +# RAM - начинается с адреса 0x20000000 и занимает 128 Кбайт; +# CCMRAM - начинается с адреса 0x10000000и занимает 64 Кбайт; +# FLASH - начинается с адреса 0x8000000 занимает 1024 Кбайт; +# Причем RAM память доступка для чтения, записи и исполнения. +# CCMRAM память доступна только на чтение и запись. +# FLASH память доступна на чтение и исполнение. +MEMORY +{ +	RAM 		(xrw)     : 	ORIGIN = 0x20000000, 	LENGTH = 128K +	CCMRAM 		(rw)      : 	ORIGIN = 0x10000000, 	LENGTH = 64K +	FLASH 		(rx)      : 	ORIGIN = 0x8000000, 	LENGTH = 1024K +} + +# Описываем выходные секции +SECTIONS +{ +	# Первая секция содержит таблицу векторов прерываний +  .isr_vector : +  { +	# Выравниваем текущую позицию на границу 4-х байт. +    . = ALIGN(4); + +	# Существует опция --gc-sections, которая позволяет собирать мусор из неиспользуемых  +	# входных разделов. И если есть разделы, которые сборщик муссора не должен трогать,  +	# то их необходимо указать в качестве аргумента функции KEEP() (аналог ключевого слова  +	# volatile). +	# Запись (*(.isr_vector)) означает разделы .isr_vector во всех объектных файлах. Т.к.  +	# обращение к разделу в общем виде выглядит так: (ИМЯ_ФАЙЛА(ИМЯ_РАЗДЕЛА))	 +    KEEP(*(.isr_vector))     + +	# Выравниваем текущую позицию на границу 4-х байт. +    . = ALIGN(4); +	 +	# Выражение ">ОБЛАСТЬ_ПАМЯТИ" указывает в какую именно область памяти будет помещенна  +	# данная секция.	В нашем слущае секция .isr_vector будет размещена во FLASH памяти. +  } >FLASH + +# ИТОГО: Секция .isr_vector, которая содержит таблицу векторов прерываний выравнивается  +# по границе 4-х байт, помечается как недоступная для сборщика мусора и размещается в начале  +# FLASH памяти микроконтроллера. + +  # Вторая секция содержит код программы. +  .text : +  { +	# Выравниваем текущую позицию на границу 4-х байт. +    . = ALIGN(4); +     +    # Указываем, что в данной секции будут хранится области .text всех +	# объектных файлов    +    *(.text)            +    *(.text*)           + +	# Защищаем от сборщика мусора секции .init и .fini +    KEEP (*(.init)) +    KEEP (*(.fini)) + +	# Выравниваем текущую позицию на границу 4-х байт. +    . = ALIGN(4); +     +	# Определяется переменная _etext, которая хранит в себе адрес конца секции .text и которая +	# может быть доступна в исходном тексте программы через объявление  +	# volaile unsigned int extern _etext; +    _etext = .;       +  } >FLASH +   +# ИТОГО: Секция .text, которая содержит код программы выравнивается по границе 4-х байт,  +# включает в себя: все секции с кодом программы во всех объектных файлах и защищенные  +от сборщика муссора секции .init и .fini во всех объектных файлах, распологается во FLASH  +памяти микроконтроллера сразу за таблицей векторов.  +Секции text, .init и .fini. располагаются в памяти в той последовательности в которой они  +объявлены в скрипте. + +  # Третья секция содержит константные данные. +  .rodata : +  { +	# Выравниваем текущую позицию на границу 4-х байт. +    . = ALIGN(4); + +	# Указываем, что в данной секции будут хранится области .rodataвсех +	# объектных файлов    +    *(.rodata)          +    *(.rodata*)   +     +	# Выравниваем текущую позицию на границу 4-х байт.       +    . = ALIGN(4); +  } >FLASH +   +  # Сохраняем в переменной _sidata  абсолютный адрес секции .data +  _sidata = LOADADDR(.data); + +  # Четвертая секция содержит инициализированные переменные. +  .data :  +  { +	# Выравниваем текущую позицию на границу 4-х байт. +    . = ALIGN(4); + +	# Сохраняем в переменной _sdata адрес текущей позиции (начала секции) +    _sdata = .;      +   +	# Указываем, что в данной секции будут хранится области .data всех +	# объектных файлов      +    *(.data)            +    *(.data*)           + +	# Выравниваем текущую позицию на границу 4-х байт. +    . = ALIGN(4); +     +    # Сохраняем в переменной _sdata адрес текущей позиции (конец секции) +    _edata = .;     +    +	# Функция AT указывает на то, что данный сектор хранится в одной области памяти  +	# (в нашем случае FLASH), а исполняться будет из другой обасти памяти (в нашем случае RAM).  +	# Есть два типа адрессов: +	# * VMA (Virtual memory address) - это run-time адрес по которому уомпилятор ожидает  +	#	видеть данные. +	# * LMA (Load memory address) - это адрес по которому линкер хранит данные.			 +			 +	#Startup должен код скопировать секцию .data из адрессов LMA в адресса VMA. +	 +  } >RAM AT> FLASH + +  # Пятая секция содержит инициализированные нулем переменные.   +  .bss : +  { +	# Сохраняем в переменной _sbss и __bss_start__  адрес текущей позиции (начала секции) +    _sbss = .;         +    __bss_start__ = _sbss; +     +	# Указываем, что в данной секции будут хранится области .bss всех +	# объектных файлов  +    *(.bss) +    *(.bss*) + +	# Выравниваем текущую позицию на границу 4-х байт. +    . = ALIGN(4); +     +    # Сохраняем в переменной _ebss и __bss_end__ адрес текущей позиции (начала секции) +    _ebss = .;          +    __bss_end__ = _ebss; +  } >RAM + +  # Шестая секция содержит кучу и стек. Размещается в самом конце RAM. +  ._user_heap_stack : +  { +    . = ALIGN(4); +    PROVIDE ( end = . ); +    PROVIDE ( _end = . ); +    . = . + _Min_Heap_Size; +    . = . + _Min_Stack_Size; +    . = ALIGN(4); +  } >RAM +} +``` + 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/nim-ru.html.markdown b/ru-ru/nim-ru.html.markdown new file mode 100644 index 00000000..0e08f1bf --- /dev/null +++ b/ru-ru/nim-ru.html.markdown @@ -0,0 +1,285 @@ +--- +language: Nim +filename: learnNim-ru.nim +contributors: +    - ["Jason J. Ayala P.", "http://JasonAyala.com"] +    - ["Dennis Felsing", "http://felsin9.de/nnis/"] +translators: +    - ["Nomadic", "https://github.com/n0madic"] +    - ["dvska", "https://github.com/dvska"] +lang: ru-ru +--- + +Nim (ранее известный, как Nimrod) — язык программирования со статической +типизацией, поддерживающий процедурный, объектно-ориентированный, +функциональный и обобщённый стили программирования. + +Nim эффективный, выразительный и элегантный. + +```nim +var                    # Объявление (и присваивание) переменных, +  буква: char = 'n'    # с указанием типа или без +  язык = "N" & "im" +  nLength : int = len(язык) +  boat: float +  правда: bool = false + +let              # Используйте let *сразу* для объявления и связывания переменных. +  ноги = 400     # ноги неизменяемый. +  руки = 2_000   # Символ _ игнорируется и удобен для длинных чисел. +  почтиПи = 3.15 + +const            # Константы вычисляются во время компиляции. Это обеспечивает +  debug = true   # производительность и полезно в выражениях этапа компиляции. +  компилироватьПлохойКод = false + +when компилироватьПлохойКод:    # `when` это `if` этапа компиляции. +  ноги = ноги + 1               # Эта ошибка никогда не будет скомпилирована. +  const ввод = readline(stdin)  # Значения констант должны быть известны во +                                # время компиляции. + +discard 1 > 2 # Примечание. Компилятор будет жаловаться, если результат +              # выражения не используется. `discard` обходит это. + +discard """ +Это может использоваться как многострочный комментарий. +Или для не поддающегося синтаксическому анализу, сломанного кода +""" + +# +# Структуры данных +# + +# Кортежи + +var +  дитя: tuple[имя: string, возраст: int]             # Кортежи определяют *как* имя поля +  сегодня: tuple[солнце: string, температура: float] # так *и* порядок полей. + +дитя = (имя: "Rudiger", возраст: 2) # Присвоить все сразу литералом () +сегодня.солнце = "Пасмурно"         # или отдельно по полям. +сегодня.температура = 20.1 + +# Последовательности + +var +  напитки: seq[string] + +напитки = @["Вода", "Сок", "Какао"] # @[V1,..,Vn] является литералом +                                    # последовательности + +напитки.add("Молоко") + +if "Молоко" in напитки: +  echo "У нас тут Молоко и ещё", напитки.len - 1, " напиток(ов)" + +let мойНапиток = напитки[2] + +# +# Определение типов +# + +# Определение собственных типов позволяет компилятору работать на вас. +# Это то, что делает статическую типизацию мощной и полезной. + +type +  Имя = string      # Псевдоним типа дает вам новый тип, который равнозначен +  Возраст = int     # старому типу, но более нагляден. +  Человек = tuple[имя: Имя, возраст: Возраст] # Определение структур данных. +  АльтернативныйСинтаксис = tuple +    fieldOne: string +    secondField: int + +var +  джон: Человек = (имя: "John B.", возраст: 17) +  новыйВозраст: int = 18 # Было бы лучше использовать Возраст, чем int + +джон.возраст = новыйВозраст # Но это все же работает, потому что int и Возраст синонимы. + +type +  Нал = distinct int          # `distinct` делает новый тип несовместимым с его +  Описание = distinct string  # базовым типом. + +var +  money: Нал = 100.Нал   # `.Нал` преобразует int в наш тип +  описание: Описание  = "Interesting".Описание + +when компилироватьПлохойКод: +  джон.возраст  = money       # Error! возраст is of type int and money is Нал +  джон.имя = описание         # Компилятор говорит: "Нельзя!" + +# +# Дополнительные типы и структуры данных +# + +# Перечисления позволяют типу иметь одно из ограниченного числа значений + +type +  Цвет = enum цКрасный, цГолубой, цЗеленый +  Направление = enum  # Альтернативный формат +    нСевер +    нЗапад +    нВосток +    нЮг +var +  напр = нСевер     # `напр` имеет тип Направление, со значением `нСевер` +  точка = цЗеленый  # `точка` имеет тип Цвет, со значением `цЗеленый` + +discard нСевер > нВосток  # Перечисления обычно являются "порядковыми" типами + +# Поддиапазоны определяют ограниченный допустимый диапазон + +type +  Кости = range[1..20]  # 🎲 Допустимым значением являются только int от 1 до 20 +var +  мой_бросок: Кости = 13 + +when компилироватьПлохойКод: +  мой_бросок = 23  # Error! + +# Массивы + +type +  СчетчикБросков = array[Кости, int]             # Массивы фиксированной длины и +  ИменаНаправлений = array[Направление, string]  # индексируются любым порядковым типом. +  Истины = array[42..44, bool] +var +  счетчик: СчетчикБросков +  направления: ИменаНаправлений +  возможны: Истины + +возможны = [false, false, false]  # Массивы создаются литералом [V1,..,Vn] +возможны[42] = true + +направления[нСевер] = "ОО. Великий белый Север!" +направления[нЗапад] = "Нет, не иди туда." + +мой_бросок = 13 +счетчик[мой_бросок] += 1 +счетчик[мой_бросок] += 1 + +var ещеМассив = ["Идекс по умолчанию", "начинается с", "0"] + +# Доступны другие структуры данных, в том числе таблицы, множества, +# списки, очереди и crit-bit деревья. +# http://nim-lang.org/docs/lib.html#collections-and-algorithms (EN) + +# +# IO и поток управления выполнением +# + +# `case`, `readLine()` + +echo "Читали какие-нибудь хорошие книги в последнее время?" + +case readLine(stdin) +of "нет", "Нет": +  echo "Пойдите в свою местную библиотеку." +of "да", "Да": +  echo "Тогда продолжим" +else: +  echo "Здорово!" + +# `while`, `if`, `continue`, `break` + +import strutils as str  # http://nim-lang.org/docs/strutils.html (EN) +echo "Я загадало число между 41 и 43. Отгадай!" +let число: int = 42 +var +  ввод_догадка: string +  догадка: int + +while догадка != число: +  ввод_догадка = readLine(stdin) + +  if ввод_догадка == "": continue  # Пропустить эту итерацию +   +  догадка = str.parseInt(ввод_догадка) + +  if догадка == 1001: +    echo("AAAAAAGGG!") +    break +  elif догадка > число: +    echo("Неа. Слишком большое.") +  elif догадка < число: +    echo(догадка, " это слишком мало") +  else: +    echo("Точнооооо!") + +# +# Итерации (циклы) +# + +for i, элем in ["Да", "Нет", "Может быть"]:  # Или просто `for элем in` +  echo(элем, " по индексу: ", i) + +for ключ, значение in items(@[(человек: "You", сила: 100), (человек: "Me", сила: 9000)]): +  echo значение + +let мояСтрока = """ +<пример> +`строки` для +тренировки +""" # Многострочная "сырая" строка + +for строка in splitLines(мояСтрока): +  echo(строка) + +for i, симв in мояСтрока:     # Индекс и символ. Или `for j in` только для символов +  if i mod 2 == 0: continue   # Компактная форма `if` +  elif симв == 'X': break +  else: echo(симв) + +# +# Процедуры +# + +type Ответ = enum оДа, оНет + +proc спрос(вопрос: string): Ответ = +  echo(вопрос, " (д/н)") +  while true: +    case readLine(stdin) +    of "д", "Д", "да", "Да": +      return Ответ.оДа  # Перечисления могут быть квалифицированы +    of "н", "Н", "нет", "Нет": +      return Ответ.оНет +    else: echo("Поточнее, да или нет") + +proc добавьСахар(количество: int = 2) =   # Значение по умолчанию 2, ничего не возвращает +  assert(количество > 0 and количество < 9000, "Диабет ☠") +  for a in 1..количество: +    echo(a, " кубик...") + +case спрос("Сахарку?") +of оДа: +  добавьСахар(3) +of оНет: +  echo "Ну немнооожко!" +  добавьСахар() +# Здесь нет необходимости в `else`. Возможны только `да` и `нет`. + +# +# FFI (интерфейс внешних функций) +# + +# Так как Nim компилируется в C, то FFI делается очень просто: + +proc strcmp(a, b: cstring): cint {.importc: "strcmp", nodecl.} + +let cmp = strcmp("C?", "Легко!") +``` + +Кроме того, Nim выделяется среди себе подобных метапрограммированием, +производительностью, функциями этапа компиляции. + +## Дальнейшее чтение (EN) + +* [Домашняя страница](http://nim-lang.org) +* [Скачать](http://nim-lang.org/download.html) +* [Сообщество](http://nim-lang.org/community.html) +* [FAQ](http://nim-lang.org/question.html) +* [Документация](http://nim-lang.org/documentation.html) +* [Руководство](http://nim-lang.org/docs/manual.html) +* [Стандартная библиотека](http://nim-lang.org/docs/lib.html) +* [Rosetta Code](http://rosettacode.org/wiki/Category:Nim) diff --git a/ru-ru/objective-c-ru.html.markdown b/ru-ru/objective-c-ru.html.markdown index d60db1d8..3baa15f8 100644 --- a/ru-ru/objective-c-ru.html.markdown +++ b/ru-ru/objective-c-ru.html.markdown @@ -781,7 +781,7 @@ MyClass *newVar = [classVar retain]; // Если classVar освободится  // автоматический подсчет ссылок (ARC).  // ARC - это особенность компилятора, который помещает "retain", "release"  // и "autorelease" автоматически за вас тогда, когда используется ARC, -// вам не нужно больше обращаться к "retain", "relase" или "autorelease" +// вам не нужно больше обращаться к "retain", "release" или "autorelease"  MyClass *arcMyClass = [[MyClass alloc] init];  // ... код, использующий объект arcMyClass  // Без ARC, вам нужно было бы вызвать: [arcMyClass release] после того, как вы diff --git a/ru-ru/pascal-ru.html.markdown b/ru-ru/pascal-ru.html.markdown new file mode 100644 index 00000000..5ea856bc --- /dev/null +++ b/ru-ru/pascal-ru.html.markdown @@ -0,0 +1,217 @@ +--- +language: Pascal +filename: learnpascal-ru.pas +contributors: +    - ["Ganesha Danu", "http://github.com/blinfoldking"] +    - ["Keith Miyake", "https://github.com/kaymmm"] +translators: +    - ["Anton 'Dart' Nikolaev", "https://github.com/dartfnm"] +lang: ru-ru +--- + + +>Pascal - это процедурный язык программирования, который Никлаус Вирт разработал в 1968–69 годах и опубликовал в 1970 году как небольшой эффективный язык, предназначенный для поощрения хороших методов программирования с использованием структурированного программирования и структурирования данных. Он назван в честь французского математика, философа и физика Блеза Паскаля. +> +>source : [wikipedia](https://ru.wikipedia.org/wiki/Паскаль_(язык_программирования))) + + + +Для компиляции и запуска программы на языке Паскаль вы можете использовать бесплатный компилятор FreePascal. [Скачать здесь](https://www.freepascal.org/)  + +Либо современный бесплатный компилятор Паскаля нового поколения под платформу .Net [PascalABC.NET](http://pascalabc.net) + +```pascal +// это комментарий +{ +    а вот это:   +    - комментарий на несколько строк +} + +//объявляем имя программы +program learn_pascal; //<-- не забываем ставить точку с запятой (;) + +const +    { +        это секция в которой вы должны объявлять константы +    } +type +    { +    	здесь вы можете объявлять собственные типы данных +    } +var +    { +        секция для объявления переменных +    } + +begin //начало основной программы +    { +        тело вашей программы +    } +end. // В конце основной программы обязательно должна стоять точка "." +``` + +```pascal +//объявление переменных +//вы можете сделать так +var a:integer; +var b:integer; +//или так +var  +    a : integer; +    b : integer; +//или даже так +var a,b : integer; +``` + +```pascal +program Learn_More; + +// Познакомимся с типами данных и с их операциями +const +    PI = 3.141592654; +    GNU = 'GNU''s Not Unix'; +        // имена константам принято давать ЗАГЛАВНЫМИ_БУКВАМИ (в верхнем регистре) +        // их значения фиксированны т.е никогда не меняются во время выполнения программы +        // содержат любой стандартный тип данных (integer, real, boolean, char, string) + +type +    ch_array : array [0..255] of char; +        // массивы - это составной тип данных +        // мы указываем индекс первого и последнего элемента массива ([0..255]) +        // здесь мы объявили новый тип данных содержащий 255 символов 'char' +        // (по сути, это просто строка - string[256]) +         +    md_array : array of array of integer; +        // массив в массиве - по сути является двумерным массивом +        // можно задать массив нулевой (0) длины, а потом динамически расширить его +        // это двумерный массив целых чисел + +//Объявление переменных +var +    int, c, d  : integer; +           // три переменные, которые содержат целые числа +           // Тип "integer" это 16-битное число в диапазоне [-32,768..32,767] +    r    : real; +           // переменная типа "real" принимает вещественные (дробные) значения +           // в диапазоне [3.4E-38..3.4E38] +    bool : boolean; +           // переменная логического типа, принимающая булевы-значения: True/False (Правда/Ложь) +    ch   : char; +           // эта переменная содержит значение кода одного символа +           // тип 'char' это 8-битное число (1 байт), так что никакого Юникода +    str  : string; +           // это переменная составного типа, являющееся строкой +           // по сути, строка это массив в 255 символов длиною, по умолчанию +           +    s    : string[50]; +           // эта строка может содержать максимум 50 символов +           // вы можете сами указать длину строки, чтобы минимизировать использование памяти +    my_str: ch_array; +           // вы можете объявлять переменные собственных типов +    my_2d : md_array; +           // динамически расширяемые массивы требуют указания длины перед их использованием. + +    // дополнительные целочисленные типы данных +    b    : byte;     // диапазон [0..255] +    shi  : shortint; // диапазон [-128..127] +    smi  : smallint; // диапазон [-32,768..32,767] (стандартный Integer) +    w    : word;     // диапазон [0..65,535] +    li   : longint;  // диапазон [-2,147,483,648..2,147,483,647] +    lw   : longword; // диапазон [0..4,294,967,295] +    c    : cardinal; // тоже что и longword +    i64  : int64;    // диапазон [-9223372036854775808..9223372036854775807] +    qw   : qword;    // диапазон [0..18,446,744,073,709,551,615] + +    // дополнительные вещественные типы данных (дробные) +    rr   : real;     // диапазон зависит от платформы (т.е. 8-бит, 16-бит и т.д.) +    rs   : single;   // диапазон [1.5E-45..3.4E38] +    rd   : double;   // диапазон [5.0E-324 .. 1.7E308] +    re   : extended; // диапазон [1.9E-4932..1.1E4932] +    rc   : comp;     // диапазон [-2E64+1 .. 2E63-1] + +Begin +    int := 1; // так мы присваиваем значение переменной +    r   := 3.14; +    ch  := 'a'; +    str := 'apple'; +    bool := true; +    // Паскаль не чувствителен к регистру +     +    // арифметические операции +    int := 1 + 1; // int = 2; заменяет предыдущее значение +    int := int + 1; // int = 2 + 1 = 3; +    int := 4 div 2; //int = 2; 'div' операция деления, с отбрасыванием дробной части +    int := 3 div 2; //int = 1; +    int := 1 div 2; //int = 0; + +    bool := true or false; // bool = true +    bool := false and true; // bool = false +    bool := true xor true; // bool = false + +    r := 3 / 2; // деления вещественных чисел с дробной частью +    r := int; // вещественной переменной можно присвоить целочисленное значение, но не наоборот + +    my_str[0] := 'a'; // для доступа к элементу массива нужно указать его индекс в квадратных скобках ([0]) + +    c := str[1]; // первая буква во всех Строках находится по индексу [1] +    str := 'hello' + 'world'; //объединяем 2 строки в одну +	 +    SetLength(my_2d,10,10); // инициализируем динамически расширяемый массив +                            // задаём размер 2х-мерного массива 10×10  +     +    // первый элемент массива лежит в индексе [0], последний [длина_массива-1] +    for c := 0 to 9 do +        for d := 0 to 9 do // переменные для счетчиков циклов должны быть объявлены +        my_2d[c,d] := c * d; +          // обращаться к многомерным массивам нужно с помощью одного набора скобок + +End. +``` + +```pascal +program Functional_Programming; + +Var +    i, dummy : integer; + +function factorial_recursion(const a: integer) : integer; +{ Функция расчёта Факториала целочисленного параметра 'a', рекурсивно. Возвращает целое значение } + +// Мы можем объявлять локальные переменные внутри своей функции: +// Var +//    local_a : integer; + +Begin +    If a >= 1 Then +        factorial_recursion := a * factorial_recursion(a-1) +        // возвращаем результат, присваивая найденное значение переменной с тем же именем, как у функции +    Else +        factorial_recursion := 1; +End; // Для завершения функции, используется символ ";" после оператора "End;" + + + +procedure get_integer( var i : integer; dummy : integer ); +{   Эта процедура ждёт от пользователя ввода целого числа и возвращает его значение через параметр i. +    Если параметр функции начинается с 'var', это означает, что его значение было передано, по ссылке, то есть, оно может использоваться не только как входное значение, но и для возвращения дополнительных результатов работы функции. +    Параметры функции (без 'var'), (такие как "dummy" (пустышка)), передаются по значению, и по сути являются - локальными переменными, таким образом изменения, внесенные внутри функции/процедуры, не влияют на значение переменной за её пределами. +} +Begin // начало процедуры +    write('Введите целое число: '); +    readln(i); // число, введённое пользователем, сохранится в переменной i +               // и её значение будет доступно вызывающей подпрограмме +     +    dummy := 4; // значение 'dummy' не будет влиять на значения переменной вне процедуры +End; // конец процедуры + +Begin // главный блок программы +    dummy := 3; +    get_integer(i, dummy); // вызываем процедуру получения числа от пользователя     +    writeln(i, '! = ', factorial_recursion(i)); // ввыводим значение факториала от i +     +    writeln('dummy = ', dummy);  +    // всегда выводит "3", поскольку фиктивная переменная не изменяется. +End. // конец программы + +``` + diff --git a/ru-ru/perl-ru.html.markdown b/ru-ru/perl-ru.html.markdown index a907ba41..a9bb683b 100644 --- a/ru-ru/perl-ru.html.markdown +++ b/ru-ru/perl-ru.html.markdown @@ -9,12 +9,12 @@ translators:  lang: ru-ru  --- -Perl 5 -- высокоуровневый мощный язык с 25-летней историей.  -Особенно хорош для обработки разнообразных текстовых данных.  +Perl -- высокоуровневый мощный язык с 25-летней историей. +Особенно хорош для обработки разнообразных текстовых данных. -Perl 5 работает более чем на 100 платформах, от портативных устройств -до мейнфреймов, и подходит как для быстрого прототипирования,  -так и для крупных проектов.  +Perl работает более чем на 100 платформах, от портативных устройств +до мейнфреймов, и подходит как для быстрого прототипирования, +так и для крупных проектов.  ```perl  # Комментарии начинаются с символа решетки. @@ -23,8 +23,8 @@ Perl 5 работает более чем на 100 платформах, от п  #### Типы переменных в Perl  #  Скалярные переменные начинаются с знака доллара $. -#  Имя переменной состоит из букв, цифр и знаков подчеркивания,  -#  начиная с буквы или подчеркивания.  +#  Имя переменной состоит из букв, цифр и знаков подчеркивания, +#  начиная с буквы или подчеркивания.  ### В Perl три основных типа переменных: скаляры, массивы, хеши. @@ -55,7 +55,7 @@ my %fruit_color = (          banana => "yellow",          ); -# Важно: вставка и поиск в хеше выполняются за константное время,  +# Важно: вставка и поиск в хеше выполняются за константное время,  # независимо от его размера.  # Скаляры, массивы и хеши подробно описаны в разделе perldata @@ -81,7 +81,7 @@ unless ( condition ) {                 }  # Это более читаемый вариант для "if (!condition)" -# Специфические Perl-овые пост-условия:  +# Специфические Perl-овые пост-условия:  print "Yow!" if $zippy;  print "We have no bananas" unless $bananas; @@ -129,7 +129,7 @@ open(my $out, ">",  "output.txt") or die "Can't open output.txt: $!";  open(my $log, ">>", "my.log")     or die "Can't open my.log: $!";  # Читать из файлового дескриптора можно с помощью оператора "<>".   -# В скалярном контексте он читает одну строку из файла, в списковом --  +# В скалярном контексте он читает одну строку из файла, в списковом --  # читает сразу весь файл, сохраняя по одной строке в элементе массива:  my $line  = <$in>; @@ -152,13 +152,13 @@ logger("We have a logger subroutine!");  #### Perl-модули -Perl-овые модули предоставляют широкий набор функциональности,  -так что вы можете не изобретать заново велосипеды, а просто скачать  -нужный модуль с CPAN (http://www.cpan.org/).  -Некоторое количество самых полезных модулей включено в стандартную  +Perl-овые модули предоставляют широкий набор функциональности, +так что вы можете не изобретать заново велосипеды, а просто скачать +нужный модуль с CPAN (http://www.cpan.org/). +Некоторое количество самых полезных модулей включено в стандартную  поставку Perl. -Раздел документации perlfaq содержит вопросы и ответы о многих частых  +Раздел документации perlfaq содержит вопросы и ответы о многих частых  задачах, и часто предлагает подходящие CPAN-модули. 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/php-ru.html.markdown b/ru-ru/php-ru.html.markdown index 181368de..af77a9ca 100644 --- a/ru-ru/php-ru.html.markdown +++ b/ru-ru/php-ru.html.markdown @@ -61,6 +61,8 @@ $int4 = 0x0F; // => 15 (ведущие символы 0x означают шес  // Двоичная запись integer доступна начиная с PHP 5.4.0.  $int5 = 0b11111111; // 255 (0b в начале означает двоичное число) +// Удаление переменной +unset($int1);  // Дробные числа  $float = 1.234; @@ -128,7 +130,7 @@ define("FOO", "something");  // Доступ к константе возможен через прямое указание её имени без знака $  echo FOO; // печатает 'something' -echo 'This outputs ' . FOO; // печатает 'This ouputs something' +echo 'This outputs ' . FOO; // печатает 'This outputs something'  /********************************   * Массивы @@ -687,45 +689,6 @@ use My\Namespace as SomeOtherNamespace;  $cls = new SomeOtherNamespace\MyClass(); -*//********************** -* Позднее статическое связывание. -* -*/ - -class ParentClass -{ -    public static function who() -    { -        echo "I'm a " . __CLASS__ . "\n"; -    } - -    public static function test() -    { -        // self ссылается на класс в котором определен метод. -        self::who(); -        // static ссылается на класс в котором метод вызван. -        static::who(); -    } -} - -ParentClass::test(); -/* -I'm a ParentClass -I'm a ParentClass -*/ - -class ChildClass extends ParentClass -{ -    public static function who() -    { -        echo "But I'm " . __CLASS__ . "\n"; -    } -} - -ChildClass::test(); -/* -I'm a ParentClass -But I'm ChildClass  /**********************  * Позднее статическое связывание. diff --git a/ru-ru/pyqt-ru.html.markdown b/ru-ru/pyqt-ru.html.markdown new file mode 100644 index 00000000..24afc03d --- /dev/null +++ b/ru-ru/pyqt-ru.html.markdown @@ -0,0 +1,86 @@ +--- +category: tool +tool: PyQT +lang: ru-ru +filename: learnpyqt-ru.py +contributors: +    - ["Nathan Hughes", "https://github.com/sirsharpest"] +translators: +    - ["Vadim Toptunov", "https://github.com/VadimToptunov"] +--- + +**Qt** - широко известный кросс-платформенный фреймворк для разработки программного обеспечения, +который может быть использован на различных софтварных и хардварных платформах без какого-либо +изменения в коде. Данный фреймворк при этом обладает мощью и скоростью нативных приложений.  +Qt и был изначально написан на *C++*. + +Данный текст является адаптацией введения в Qt на C++ под авторством Алексея Ковальчука для pyqt. + + +```python + +def window(): +    # Создайте объект приложения  +    app = QtGui.QApplication(sys.argv) +    # Создайте виджет, где будет находиться наш лейбл +    w = QtGui.QWidget() +    # Добавьте лейбл в виджет +    b = QtGui.QLabel(w) +    # Задайте текст для лейбла +    b.setText("Hello World!") +    # Задайте информация о размере и расположении  +    w.setGeometry(100, 100, 200, 50) +    b.move(50, 20) +    # Задайте заголовок окна  +    w.setWindowTitle("PyQt") +    # Все ранее написанное выводится на экран +    w.show() +    # Настройка +    sys.exit(app.exec_()) + +if __name__ == '__main__': +    window() + +``` + +Для того, чтобы получить более продвинутые функции приложения в pyqt, нам необходимо  +обратить внимание на создание дополнительных элементов. Ниже представлено создание всплывающего диалогового окна, которое просит пользователя подтвердить его решение или предоставить какую-либо  +информацию. + +```Python  +import sys +from PyQt4.QtGui import * +from PyQt4.QtCore import * + + +def window(): +    app = QApplication(sys.argv) +    w = QWidget() +    # Создайте кнопку и прикрепите ее к виджету w +    b = QPushButton(w) +    b.setText("Press me") +    b.move(50, 50) +    # Укажите b вызвать эту функцию при клике мышкой +    # Заметьте, что в вызове функции отсутствуют "()" +    b.clicked.connect(showdialog) +    w.setWindowTitle("PyQt Dialog") +    w.show() +    sys.exit(app.exec_()) + +Данная функция должна создавать диалоговое окно с кнопкой, которая ждет клика по себе  +и затем завершает программу. + +def showdialog(): +    d = QDialog() +    b1 = QPushButton("ok", d) +    b1.move(50, 50) +    d.setWindowTitle("Dialog") +    # Эта модальность сообщает всплывающему окну блокировать родительский элемент, пока он активен +    d.setWindowModality(Qt.ApplicationModal) +    # Процесс завершается по клику мышкой +    b1.clicked.connect(sys.exit) +    d.exec_() + +if __name__ == '__main__': +    window() +``` diff --git a/ru-ru/python-ru.html.markdown b/ru-ru/python-ru.html.markdown index 43142eff..e0e53b9c 100644 --- a/ru-ru/python-ru.html.markdown +++ b/ru-ru/python-ru.html.markdown @@ -1,27 +1,30 @@  --- -language: python +language: Python  lang: ru-ru  contributors:      - ["Louie Dinh", "http://ldinh.ca"] +    - ["Steven Basart", "http://github.com/xksteven"]  translators: -    - ["Yury Timofeev", "http://twitter.com/gagar1n"]      - ["Andre Polykanine", "https://github.com/Oire"] +    - ["Anton Grouchtchak", "https://github.com/Teraskull"]  filename: learnpython-ru.py  ---  Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из  самых популярных языков. Я влюбился в Python за понятный и доходчивый синтаксис  — это -почти исполняемый псевдокод. +почти что исполняемый псевдокод.  С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh)  или louiedinh [at] [почтовый сервис Google] -Замечание: Эта статья относится к Python 2.7, но должно работать и в других версиях Python 2.x. -Чтобы изучить Python 3.x, обратитесь к статье по Python 3. +Замечание: Эта статья относится только к Python 3. +Если вы хотите изучить Python 2.7, обратитесь к другой статье.  ```python +  # Однострочные комментарии начинаются с символа решётки. -""" Многострочный текст может быть  + +""" Многострочный текст может быть      записан, используя 3 знака " и обычно используется      в качестве встроенной документации  """ @@ -31,323 +34,397 @@ filename: learnpython-ru.py  ####################################################  # У вас есть числа -3 #=> 3 +3  # => 3  # Математика работает вполне ожидаемо -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7 - -# А вот деление немного сложнее. В этом случае происходит деление  -# целых чисел, и результат автоматически округляется в меньшую сторону. -5 / 2 #=> 2 - -# Чтобы делить правильно, сначала нужно немного узнать о числах -# с плавающей запятой. -2.0     # Это число с плавающей запятой -11.0 / 4.0 #=> 2.75 Вооот... Так гораздо лучше +1 + 1   # => 2 +8 - 1   # => 7 +10 * 2  # => 20 +35 / 5  # => 7.0  # Результат целочисленного деления округляется в меньшую сторону  # как для положительных, так и для отрицательных чисел. -5 // 3     # => 1 -5.0 // 3.0 # => 1.0 # работает и для чисел с плавающей запятой --5 // 3  # => -2 +5 // 3      # => 1 +-5 // 3     # => -2 +5.0 // 3.0  # => 1.0 # работает и для чисел с плавающей запятой  -5.0 // 3.0 # => -2.0 +# # Результат деления возвращает число с плавающей запятой +10.0 / 3  # => 3.3333333333333335 +  # Остаток от деления -7 % 3 # => 1 +7 % 3  # => 1  # Возведение в степень -2**4 # => 16 +2**3  # => 8  # Приоритет операций указывается скобками -(1 + 3) * 2 #=> 8 +1 + 3 * 2    # => 7 +(1 + 3) * 2  # => 8 -# Логические операторы -# Обратите внимание: ключевые слова «and» и «or» чувствительны к регистру букв -True and False #=> False -False or True #=> True - -# Обратите внимание, что логические операторы используются и с целыми числами -0 and 2 #=> 0 --5 or 0 #=> -5 -0 == False #=> True -2 == True #=> False -1 == True #=> True +# Булевы значения - примитивы (Обратите внимание на заглавную букву) +True   # => True +False  # => False  # Для отрицания используется ключевое слово not -not True #=> False -not False #=> True +not True   # => False +not False  # => True + +# Булевы операторы +# Обратите внимание: ключевые слова "and" и "or" чувствительны к регистру букв +True and False  # => False +False or True   # => True + +# True и False на самом деле 1 и 0, но с разными ключевыми словами +True + True  # => 2 +True * 8     # => 8 +False - 5    # => -5 + +# Операторы сравнения обращают внимание на числовое значение True и False +0 == False   # => True +1 == True    # => True +2 == True    # => False +-5 != False  # => True + +# Использование булевых логических операторов на типах int превращает их в булевы значения, но возвращаются оригинальные значения +# Не путайте с bool(ints) и bitwise and/or (&,|) +bool(0)   # => False +bool(4)   # => True +bool(-6)  # => True +0 and 2   # => 0 +-5 or 0   # => -5  # Равенство — это == -1 == 1 #=> True -2 == 1 #=> False +1 == 1  # => True +2 == 1  # => False  # Неравенство — это != -1 != 1 #=> False -2 != 1 #=> True +1 != 1  # => False +2 != 1  # => True  # Ещё немного сравнений -1 < 10 #=> True -1 > 10 #=> False -2 <= 2 #=> True -2 >= 2 #=> True - -# Сравнения могут быть записаны цепочкой! -1 < 2 < 3 #=> True -2 < 3 < 2 #=> False +1 < 10  # => True +1 > 10  # => False +2 <= 2  # => True +2 >= 2  # => True + +# Проверка, находится ли значение в диапазоне +1 < 2 and 2 < 3  # => True +2 < 3 and 3 < 2  # => False + +# Сравнения могут быть записаны цепочкой +1 < 2 < 3  # => True +2 < 3 < 2  # => False + +# (is vs. ==) ключевое слово is проверяет, относятся ли две переменные к одному и тому же объекту, но == проверяет если указанные объекты имеют одинаковые значения. +a = [1, 2, 3, 4]  # a указывает на новый список, [1, 2, 3, 4] +b = a             # b указывает на то, что указывает a +b is a            # => True, a и b относятся к одному и тому же объекту +b == a            # => True, Объекты a и b равны +b = [1, 2, 3, 4]  # b указывает на новый список, [1, 2, 3, 4] +b is a            # => False, a и b не относятся к одному и тому же объекту +b == a            # => True, Объекты a и b равны  # Строки определяются символом " или '  "Это строка."  'Это тоже строка.' -# И строки тоже можно складывать! -"Привет " + "мир!" #=> "Привет мир!" +# И строки тоже могут складываться! Хотя лучше не злоупотребляйте этим. +"Привет " + "мир!"  # => "Привет мир!" -# ... или умножать -"Привет" * 3  # => "ПриветПриветПривет" +# Строки (но не переменные) могут быть объединены без использования '+' +"Привет " "мир!"  # => "Привет мир!"  # Со строкой можно работать, как со списком символов -"Это строка"[0] #=> 'Э' +"Привет мир!"[0]  # => 'П' -# Символ % используется для форматирования строк, например: -"%s могут быть %s" % ("строки", "интерполированы") +# Вы можете найти длину строки +len("Это строка")  # => 10 -# Новый способ форматирования строк — использование метода format. -# Это предпочитаемый способ. -"{0} могут быть {1}".format("строки", "форматированы") +# Вы также можете форматировать, используя f-строки (в Python 3.6+) +name = "Рейко" +f"Она сказала, что ее зовут {name}." # => "Она сказала, что ее зовут Рейко" +# Вы можете поместить любой оператор Python в фигурные скобки, и он будет выведен в строке. +f"{name} состоит из {len(name)} символов." # => "Рэйко состоит из 5 символов." -# Если вы не хотите считать, можете использовать ключевые слова. -"{name} хочет есть {food}".format(name="Боб", food="лазанью")  # None является объектом -None #=> None +None  # => None -# Не используйте оператор равенства '=='' для сравнения  -# объектов с None. Используйте для этого «is» -"etc" is None #=> False -None is None  #=> True +# Не используйте оператор равенства "==" для сравнения +# объектов с None. Используйте для этого "is" +"etc" is None  # => False +None is None   # => True -# Оператор 'is' проверяет идентичность объектов. Он не  -# очень полезен при работе с примитивными типами, но  -# зато просто незаменим при работе с объектами. - -# None, 0 и пустые строки/списки равны False. +# None, 0 и пустые строки/списки/словари/кортежи приводятся к False.  # Все остальные значения равны True -0 == False  #=> True -"" == False #=> True +bool(0)   # => False +bool("")  # => False +bool([])  # => False +bool({})  # => False +bool(())  # => False  #################################################### -## 2. Переменные и коллекции +## 2. Переменные и Коллекции  #################################################### -# В Python есть оператор print, доступный в версиях 2.x, но удалённый в версии 3 -print "Я Python. Приятно познакомиться!" -# В Python также есть функция print(), доступная в версиях 2.7 и 3, -# Но для версии 2.7 нужно добавить следующий импорт модуля (раскомментируйте)): -# from __future__ import print_function -print("Я тоже Python! ") +# В Python есть функция Print +print("Я Python. Приятно познакомиться!")  # => Я Python. Приятно познакомиться! + +# По умолчанию функция, print() также выводит новую строку в конце. +# Используйте необязательный аргумент end, чтобы изменить последнюю строку. +print("Привет мир", end="!")  # => Привет мир! + +# Простой способ получить входные данные из консоли +input_string_var = input("Введите данные: ")  # Возвращает данные в виде строки +# Примечание: в более ранних версиях Python метод input() назывался raw_input()  # Объявлять переменные перед инициализацией не нужно. -some_var = 5    # По соглашению используется нижний_регистр_с_подчёркиваниями -some_var #=> 5 +# По соглашению используется нижний_регистр_с_подчёркиваниями +some_var = 5 +some_var  # => 5 -# При попытке доступа к неинициализированной переменной -# выбрасывается исключение. -# См. раздел «Поток управления» для информации об исключениях. -some_other_var  # Выбрасывает ошибку именования +# При попытке доступа к неинициализированной переменной выбрасывается исключение. +# Об исключениях см. раздел "Поток управления и итерируемые объекты". +some_unknown_var  # Выбрасывает ошибку NameError -# if может быть использован как выражение -"yahoo!" if 3 > 2 else 2 #=> "yahoo!" +# if можно использовать как выражение +# Эквивалент тернарного оператора '?:' в C +"да!" if 0 > 1 else "нет!"  # => "нет!"  # Списки хранят последовательности  li = []  # Можно сразу начать с заполненного списка  other_li = [4, 5, 6] -# строка разделена в список -a="adambard" -list(a) #=> ['a','d','a','m','b','a','r','d'] - -# Объекты добавляются в конец списка методом append -li.append(1)    # [1] -li.append(2)    # [1, 2] -li.append(4)    # [1, 2, 4] -li.append(3)    # [1, 2, 4, 3] -# И удаляются с конца методом pop -li.pop()        #=> возвращает 3 и li становится равен [1, 2, 4] +# Объекты добавляются в конец списка методом append() +li.append(1)  # [1] +li.append(2)  # [1, 2] +li.append(4)  # [1, 2, 4] +li.append(3)  # [1, 2, 4, 3] +# И удаляются с конца методом pop() +li.pop()      # => возвращает 3 и li становится равен [1, 2, 4]  # Положим элемент обратно -li.append(3)    # [1, 2, 4, 3]. +li.append(3)  # [1, 2, 4, 3].  # Обращайтесь со списком, как с обычным массивом -li[0] #=> 1 -# Присваивайте новые значения уже инициализированным индексам с помощью = -li[0] = 42 -li[0]  # => 42 -li[0] = 1  # Обратите внимание: возвращаемся на исходное значение +li[0]  # => 1 +  # Обратимся к последнему элементу -li[-1] #=> 3 +li[-1]  # => 3  # Попытка выйти за границы массива приведёт к ошибке индекса -li[4] # Выдаёт IndexError +li[4]  # Выбрасывает ошибку IndexError  # Можно обращаться к диапазону, используя так называемые срезы  # (Для тех, кто любит математику, это называется замкнуто-открытый интервал). -li[1:3] #=> [2, 4] -# Опускаем начало -li[2:] #=> [4, 3] -# Опускаем конец -li[:3] #=> [1, 2, 4] -# Выбираем каждый второй элемент -li[::2]   # =>[1, 4] -# Переворачиваем список -li[::-1]   # => [3, 4, 2, 1] +li[1:3]   # Вернуть список из индекса с 1 по 3 => [2, 4] +li[2:]    # Вернуть список, начиная с индекса 2 => [4, 3] +li[:3]    # Вернуть список с начала до индекса 3  => [1, 2, 4] +li[::2]   # Вернуть список, выбирая каждую вторую запись => [1, 4] +li[::-1]  # Вернуть список в обратном порядке => [3, 4, 2, 1]  # Используйте сочетания всего вышеназванного для выделения более сложных срезов  # li[начало:конец:шаг] +# Сделать однослойную глубокую копию, используя срезы +li2 = li[:]  # => li2 = [1, 2, 4, 3], но (li2 is li) вернет False. +  # Удаляем произвольные элементы из списка оператором del -del li[2] # li теперь [1, 2, 3] +del li[2]  # [1, 2, 3] + +# Удалить первое вхождение значения +li.remove(2)  # [1, 3] +li.remove(2)  # Выбрасывает ошибку ValueError поскольку 2 нет в списке + +# Вставить элемент по определенному индексу +li.insert(1, 2)  # [1, 2, 3] + +# Получить индекс первого найденного элемента, соответствующего аргументу +li.index(2)  # => 1 +li.index(4)  # Выбрасывает ошибку ValueError поскольку 4 нет в списке  # Вы можете складывать, или, как ещё говорят, конкатенировать списки -li + other_li #=> [1, 2, 3, 4, 5, 6]  — Замечание: li и other_li не изменяются  # Обратите внимание: значения li и other_li при этом не изменились. +li + other_li  # => [1, 2, 3, 4, 5, 6] -# Объединять списки можно методом extend +# Объединять списки можно методом extend()  li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6] -# Проверить элемент на вхождение в список можно оператором in -1 in li #=> True +# Проверить элемент на наличие в списке можно оператором in +1 in li  # => True  # Длина списка вычисляется функцией len -len(li) #=> 6 +len(li)  # => 6 -# Кортежи — это такие списки, только неизменяемые +# Кортежи похожи на списки, только неизменяемые  tup = (1, 2, 3) -tup[0] #=> 1 -tup[0] = 3  # Выдаёт TypeError +tup[0]  # => 1 +tup[0] = 3  # Выбрасывает ошибку TypeError + +# Обратите внимание, что кортеж длины 1 должен иметь запятую после последнего элемента, но кортежи другой длины, даже 0, не должны. +type((1))   # => <class 'int'> +type((1,))  # => <class 'tuple'> +type(())    # => <class 'tuple'>  # Всё то же самое можно делать и с кортежами -len(tup) #=> 3 -tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) -tup[:2] #=> (1, 2) -2 in tup #=> True +len(tup)         # => 3 +tup + (4, 5, 6)  # => (1, 2, 3, 4, 5, 6) +tup[:2]          # => (1, 2) +2 in tup         # => True  # Вы можете распаковывать кортежи (или списки) в переменные -a, b, c = (1, 2, 3)     # a == 1, b == 2 и c == 3 +a, b, c = (1, 2, 3)  # a == 1, b == 2 и c == 3 +# Вы также можете сделать расширенную распаковку +a, *b, c = (1, 2, 3, 4) # a теперь 1, b теперь [2, 3] и c теперь 4  # Кортежи создаются по умолчанию, если опущены скобки -d, e, f = 4, 5, 6 +d, e, f = 4, 5, 6  # кортеж 4, 5, 6 распаковывается в переменные d, e и f +# соответственно, d = 4, e = 5 и f = 6  # Обратите внимание, как легко поменять местами значения двух переменных -e, d = d, e     # теперь d == 5, а e == 4 +e, d = d, e  # теперь d == 5, а e == 4 -#  Словари содержат ассоциативные массивы + +# Словари содержат ассоциативные массивы  empty_dict = {}  # Вот так описывается предзаполненный словарь  filled_dict = {"one": 1, "two": 2, "three": 3} -# Значения извлекаются так же, как из списка, с той лишь разницей, -# что индекс — у словарей он называется ключом — не обязан быть числом -filled_dict["one"] #=> 1 +# Обратите внимание, что ключи для словарей должны быть неизменяемыми типами. Это +# сделано для того, чтобы ключ может быть преобразован в хеш для быстрого поиска. +# Неизменяемые типы включают целые числа, числа с плавающей запятой, строки, кортежи. +invalid_dict = {[1,2,3]: "123"}  # => Выбрасывает ошибку TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]}   # Однако значения могут быть любого типа. + +# Поиск значений с помощью [] +filled_dict["one"]  # => 1 -# Можно получить все ключи в виде списка с помощью метода keys -filled_dict.keys() #=> ["three", "two", "one"] -# Замечание: сохранение порядка ключей в словаре не гарантируется -# Ваши результаты могут не совпадать с этими. +# Все ключи в виде списка получаются с помощью метода keys(). +# Его вызов нужно обернуть в list(), так как обратно мы получаем +# итерируемый объект, о которых поговорим позднее. Примечание - для Python +# версии <3.7, порядок словарных ключей не гарантируется. Ваши результаты могут +# не точно соответствовать приведенному ниже примеру. Однако, начиная с Python 3.7 +# элементы в словаре сохраняют порядок, в котором они вставляются в словарь. +list(filled_dict.keys())  # => ["three", "two", "one"] в Python <3.7 +list(filled_dict.keys())  # => ["one", "two", "three"] в Python 3.7+ -# Можно получить и все значения в виде списка, используйте метод values -filled_dict.values() #=> [3, 2, 1] + +# Все значения в виде списка можно получить с помощью values(). +# И снова нам нужно обернуть вызов в list(), чтобы превратить +# итерируемый объект в список.  # То же самое замечание насчёт порядка ключей справедливо и здесь +list(filled_dict.values())  # => [3, 2, 1] в Python <3.7 +list(filled_dict.values())  # => [1, 2, 3] в Python 3.7+ -# При помощи оператора in можно проверять ключи на вхождение в словарь -"one" in filled_dict #=> True -1 in filled_dict #=> False +# При помощи ключевого слова in можно проверять наличие ключей в словаре +"one" in filled_dict  # => True +1 in filled_dict      # => False -# Попытка получить значение по несуществующему ключу выбросит ошибку ключа -filled_dict["four"] # KeyError +# Попытка получить значение по несуществующему ключу выбросит ошибку KeyError +filled_dict["four"]  # Выбрасывает ошибку KeyError  # Чтобы избежать этого, используйте метод get() -filled_dict.get("one") #=> 1 -filled_dict.get("four") #=> None -# Метод get также принимает аргумент по умолчанию, значение которого будет -# возвращено при отсутствии указанного ключа -filled_dict.get("one", 4) #=> 1 -filled_dict.get("four", 4) #=> 4 -# Обратите внимание, что filled_dict.get("four") всё ещё => None -# (get не устанавливает значение элемента словаря) - -# Присваивайте значение ключам так же, как и в списках -filled_dict["four"] = 4  # теперь filled_dict["four"] => 4 +filled_dict.get("one")      # => 1 +filled_dict.get("four")     # => None +# Метод get поддерживает аргумент по умолчанию, когда значение отсутствует +filled_dict.get("one", 4)   # => 1 +filled_dict.get("four", 4)  # => 4  # Метод setdefault() вставляет пару ключ-значение, только если такого ключа нет -filled_dict.setdefault("five", 5) #filled_dict["five"] возвращает 5 -filled_dict.setdefault("five", 6) #filled_dict["five"] по-прежнему возвращает 5 +filled_dict.setdefault("five", 5)  # filled_dict["five"] возвращает 5 +filled_dict.setdefault("five", 6)  # filled_dict["five"] по-прежнему возвращает 5 + +# Добавление элементов в словарь +filled_dict.update({"four":4})  # => {"one": 1, "two": 2, "three": 3, "four": 4} +filled_dict["four"] = 4         # Другой способ добавления элементов + +# Удаляйте ключи из словаря с помощью ключевого слова del +del filled_dict["one"]  # Удаляет ключ "one" из словаря + +# После Python 3.5 вы также можете использовать дополнительные параметры распаковки +{'a': 1, **{'b': 2}}  # => {'a': 1, 'b': 2} +{'a': 1, **{'a': 2}}  # => {'a': 2} +  # Множества содержат... ну, в общем, множества -# (которые похожи на списки, только в них не может быть дублирующихся элементов)  empty_set = set() -# Инициализация множества набором значений -some_set = set([1,2,2,3,4]) # some_set теперь равно set([1, 2, 3, 4]) - -# Порядок сортировки не гарантируется, хотя иногда они выглядят отсортированными -another_set = set([4, 3, 2, 2, 1])  # another_set теперь set([1, 2, 3, 4]) +# Инициализация множества набором значений. +# Да, оно выглядит примерно как словарь. Ну извините, так уж вышло. +filled_set = {1, 2, 2, 3, 4}  # => {1, 2, 3, 4} -# Начиная с Python 2.7, вы можете использовать {}, чтобы объявить множество -filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} +# Similar to keys of a dictionary, elements of a set have to be immutable. +# Как и ключи словаря, элементы множества должны быть неизменяемыми. +invalid_set = {[1], 1}  # => Выбрасывает ошибку TypeError: unhashable type: 'list' +valid_set = {(1,), 1} -# Добавление новых элементов в множество -filled_set.add(5) # filled_set равно {1, 2, 3, 4, 5} +# Множеству можно назначать новую переменную +filled_set = some_set +filled_set.add(5)  # {1, 2, 3, 4, 5} +# В множествах нет повторяющихся элементов +filled_set.add(5)  # {1, 2, 3, 4, 5}  # Пересечение множеств: &  other_set = {3, 4, 5, 6} -filled_set & other_set #=> {3, 4, 5} +filled_set & other_set  # => {3, 4, 5}  # Объединение множеств: | -filled_set | other_set #=> {1, 2, 3, 4, 5, 6} +filled_set | other_set  # => {1, 2, 3, 4, 5, 6}  # Разность множеств: - -{1,2,3,4} - {2,3,5} #=> {1, 4} +{1, 2, 3, 4} - {2, 3, 5}  # => {1, 4} -# Проверка на вхождение во множество: in -2 in filled_set #=> True -10 in filled_set #=> False +# Симметричная разница: ^ +{1, 2, 3, 4} ^ {2, 3, 5}  # => {1, 4, 5} + +# Проверить, является ли множество слева надмножеством множества справа +{1, 2} >= {1, 2, 3}  # => False + +# Проверить, является ли множество слева подмножеством множества справа +{1, 2} <= {1, 2, 3}  # => True + +# Проверка на наличие в множестве: in +2 in filled_set   # => True +10 in filled_set  # => False + +# Сделать однослойную глубокую копию +filled_set = some_set.copy()  # {1, 2, 3, 4, 5} +filled_set is some_set        # => False  #################################################### -## 3. Поток управления +## 3. Поток управления и итерируемые объекты  #################################################### -# Для начала заведём переменную +# Для начала создадим переменную  some_var = 5  # Так выглядит выражение if. Отступы в python очень важны! -# результат: «some_var меньше, чем 10» +# Конвенция заключается в использовании четырех пробелов, а не табуляции. +# Pезультат: "some_var меньше, чем 10"  if some_var > 10: -    print("some_var намного больше, чем 10.") -elif some_var < 10:    # Выражение elif необязательно. +    print("some_var точно больше, чем 10.") +elif some_var < 10:  # Выражение elif необязательно.      print("some_var меньше, чем 10.") -else:           # Это тоже необязательно. +else:                # Это тоже необязательно.      print("some_var равно 10.")  """ -Циклы For проходят по спискам - -Результат: +Циклы For проходят по спискам. +Выводит:      собака — это млекопитающее      кошка — это млекопитающее      мышь — это млекопитающее  """  for animal in ["собака", "кошка", "мышь"]: -    # Можете использовать оператор % для интерполяции форматированных строк -    print("%s — это млекопитающее" % animal) -     +    # Можете использовать format() для интерполяции форматированных строк +    print("{} — это млекопитающее".format(animal)) +  """ -«range(число)» возвращает список чисел +"range(число)" возвращает список чисел  от нуля до заданного числа -Результат: +Выводит:      0      1      2 @@ -357,8 +434,42 @@ for i in range(4):      print(i)  """ +"range(нижнее, верхнее)" возвращает список чисел +от нижнего числа к верхнему +Выводит: +    4 +    5 +    6 +    7 +""" +for i in range(4, 8): +    print(i) + +""" +"range(нижнее, верхнее, шаг)" возвращает список чисел +от нижнего числа к верхнему, от нижнего числа к верхнему, увеличивая +шаг за шагом. Если шаг не указан, значение по умолчанию - 1. +Выводит: +    4 +    6 +""" +for i in range(4, 8, 2): +    print(i) + +""" +Чтобы перебрать список и получить индекс и значение каждого элемента в списке +Выводит: +    0 собака +    1 кошка +    2 мышь +""" +animals = ["собака", "кошка", "мышь"] +for i, value in enumerate(animals): +    print(i, value) + +"""  Циклы while продолжаются до тех пор, пока указанное условие не станет ложным. -Результат: +Выводит:      0      1      2 @@ -370,20 +481,81 @@ while x < 4:      x += 1  # Краткая запись для x = x + 1  # Обрабатывайте исключения блоками try/except - -# Работает в Python 2.6 и выше:  try:      # Чтобы выбросить ошибку, используется raise      raise IndexError("Это ошибка индекса")  except IndexError as e: -    # pass — это просто отсутствие оператора. Обычно здесь происходит -    # восстановление после ошибки. -    pass +    pass                  # pass — это просто отсутствие оператора. Обычно здесь происходит восстановление после ошибки.  except (TypeError, NameError): -    pass    # Несколько исключений можно обработать вместе, если нужно. -else:   # Необязательное выражение. Должно следовать за последним блоком except -    print("Всё хорошо!")   # Выполнится, только если не было никаких исключений +    pass                  # Несколько исключений можно обработать вместе, если нужно. +else:                     # Необязательное выражение. Должно следовать за последним блоком except +    print("Всё хорошо!")  # Выполнится, только если не было никаких исключений +finally:                  # Выполнить при любых обстоятельствах +    print("Мы можем очистить ресурсы здесь") + +# Вместо try/finally чтобы очистить ресурсы, можно использовать оператор with +with open("myfile.txt") as f: +    for line in f: +        print(line) + +# Запись в файл +contents = {"aa": 12, "bb": 21} +with open("myfile1.txt", "w+") as file: +    file.write(str(contents))        # Записывает строку в файл + +with open("myfile2.txt", "w+") as file: +    file.write(json.dumps(contents)) # Записывает объект в файл + +# Чтение из файла +with open('myfile1.txt', "r+") as file: +    contents = file.read()           # Читает строку из файла +print(contents) +# print: {"aa": 12, "bb": 21} + +with open('myfile2.txt', "r+") as file: +    contents = json.load(file)       # Читает объект json из файла +print(contents) +# print: {"aa": 12, "bb": 21} + + +# Python предоставляет фундаментальную абстракцию, +# которая называется итерируемым объектом (Iterable). +# Итерируемый объект — это объект, который воспринимается как последовательность. +# Объект, который возвратила функция range(), итерируемый. + +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable)  # => dict_keys(['one', 'two', 'three']). Это объект, реализующий интерфейс Iterable + +# Мы можем проходить по нему циклом. +for i in our_iterable: +    print(i)  # Выводит one, two, three + +# Но мы не можем обращаться к элементу по индексу. +our_iterable[1]  # Выбрасывает ошибку TypeError + +# Итерируемый объект знает, как создавать итератор. +our_iterator = iter(our_iterable) + +# Итератор может запоминать состояние при проходе по объекту. +# Мы получаем следующий объект, вызывая функцию next(). +next(our_iterator)  # => "one" +# Он сохраняет состояние при вызове next(). +next(our_iterator)  # => "two" +next(our_iterator)  # => "three" + +# Возвратив все данные, итератор выбрасывает исключение StopIterator +next(our_iterator)  # Выбрасывает исключение StopIteration + +# Мы можем проходить по нему циклом. +our_iterator = iter(our_iterable) +for i in our_iterator: +    print(i)  # Выводит one, two, three + +# Вы можете получить сразу все элементы итератора, вызвав на нём функцию list(). +list(our_iterable)  # => Возвращает ["one", "two", "three"] +list(our_iterator)  # => Возвращает [] потому что состояние сохраняется  #################################################### @@ -393,30 +565,28 @@ else:   # Необязательное выражение. Должно след  # Используйте def для создания новых функций  def add(x, y):      print("x равен %s, а y равен %s" % (x, y)) -    return x + y    # Возвращайте результат с помощью ключевого слова return +    return x + y  # Возвращайте результат с помощью ключевого слова return  # Вызов функции с аргументами -add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвращает 11 +add(5, 6)  # => Выводит "x равен 5, а y равен 6" и возвращает 11  # Другой способ вызова функции — вызов с именованными аргументами -add(y=6, x=5)   # Именованные аргументы можно указывать в любом порядке. +add(y=6, x=5)  # Именованные аргументы можно указывать в любом порядке. -# Вы можете определить функцию, принимающую переменное число аргументов, -# которые будут интерпретированы как кортеж, если вы не используете * +# Вы можете определить функцию, принимающую переменное число аргументов  def varargs(*args):      return args -varargs(1, 2, 3) #=> (1,2,3) +varargs(1, 2, 3)  # => (1,2,3)  # А также можете определить функцию, принимающую переменное число -# именованных аргументов, которые будут интерпретированы как словарь, -# если вы не используете ** +# именованных аргументов  def keyword_args(**kwargs):      return kwargs  # Вызовем эту функцию и посмотрим, что из этого получится -keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} +keyword_args(big="foot", loch="ness")  # => {"big": "foot", "loch": "ness"}  # Если хотите, можете использовать оба способа одновременно  def all_the_args(*args, **kwargs): @@ -432,77 +602,134 @@ all_the_args(1, 2, a=3, b=4) выводит:  # Используйте символ * для распаковки кортежей и ** для распаковки словарей  args = (1, 2, 3, 4)  kwargs = {"a": 3, "b": 4} -all_the_args(*args) # эквивалентно foo(1, 2, 3, 4) -all_the_args(**kwargs) # эквивалентно foo(a=3, b=4) -all_the_args(*args, **kwargs) # эквивалентно foo(1, 2, 3, 4, a=3, b=4) - -# вы можете передавать переменное число позиционных или именованных аргументов -# другим функциям, которые их принимают, распаковывая их с помощью -# * или ** соответственно -def pass_all_the_args(*args, **kwargs): -    all_the_args(*args, **kwargs) -    print varargs(*args) -    print keyword_args(**kwargs) +all_the_args(*args)            # эквивалентно all_the_args(1, 2, 3, 4) +all_the_args(**kwargs)         # эквивалентно all_the_args(a=3, b=4) +all_the_args(*args, **kwargs)  # эквивалентно all_the_args(1, 2, 3, 4, a=3, b=4) + +# Возврат нескольких значений (с назначением кортежей) +def swap(x, y): +    return y, x  # Возвращает несколько значений в виде кортежа без скобок. +                 # (Примечание: скобки исключены, но могут быть включены) + +x = 1 +y = 2 +x, y = swap(x, y)     # => x = 2, y = 1 +# (x, y) = swap(x,y)  # Снова, скобки были исключены, но могут быть включены.  # Область определения функций  x = 5 -def setX(num): +def set_x(num):      # Локальная переменная x — это не то же самое, что глобальная переменная x -    x = num # => 43 -    print (x) # => 43 -     -def setGlobalX(num): +    x = num   # => 43 +    print(x)  # => 43 + +def set_global_x(num):      global x -    print (x) # => 5 -    x = num # Глобальная переменная x теперь равна 6 -    print (x) # => 6 +    print(x)  # => 5 +    x = num   # Глобальная переменная x теперь равна 6 +    print(x)  # => 6 -setX(43) -setGlobalX(6) +set_x(43) +set_global_x(6) -# В Python функции — «объекты первого класса» +# Python имеет функции первого класса  def create_adder(x):      def adder(y):          return x + y      return adder  add_10 = create_adder(10) -add_10(3) #=> 13 +add_10(3)  # => 13  # Также есть и анонимные функции -(lambda x: x > 2)(3) #=> True +(lambda x: x > 2)(3)                  # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1)  # => 5  # Есть встроенные функции высшего порядка -map(add_10, [1,2,3]) #=> [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] +list(map(add_10, [1, 2, 3]))          # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1]))  # => [4, 2, 3] + +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7]))  # => [6, 7] + +# Для удобного отображения и фильтрации можно использовать списочные интерпретации +# Интерпретация списка сохраняет вывод в виде списка, который сам может быть вложенным списком +[add_10(i) for i in [1, 2, 3]]         # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5]  # => [6, 7] + +# Вы также можете создавать интерпретации множеств и словарей. +{x for x in 'abcddeef' if x not in 'abc'}  # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)}  # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} -# Для удобного отображения и фильтрации можно использовать списочные включения -[add_10(i) for i in [1, 2, 3]]  #=> [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]  #################################################### -## 5. Классы +## 5. Модули  #################################################### -# Чтобы получить класс, мы наследуемся от object. -class Human(object): +# Вы можете импортировать модули +import math +print(math.sqrt(16))  # => 4.0 + +# Вы можете получить определенные функции из модуля +from math import ceil, floor +print(ceil(3.7))   # => 4.0 +print(floor(3.7))  # => 3.0 + +# Вы можете импортировать все функции из модуля. +# Предупреждение: это не рекомендуется +from math import * -    # Атрибут класса. Он разделяется всеми экземплярами этого класса -    species = "H. sapiens" +# Вы можете сократить имена модулей +import math as m +math.sqrt(16) == m.sqrt(16)  # => True + +# Модули Python - это обычные файлы Python. Вы +# можете писать свои собственные и импортировать их. Имя +# модуля совпадает с именем файла. + +# Вы можете узнать, какие функции и атрибуты +# определены в модуле. +import math +dir(math) + +# Если у вас есть скрипт Python с именем math.py в той же папке, +# что и ваш текущий скрипт, файл math.py будет +# будет загружен вместо встроенного модуля Python. +# Это происходит потому, что локальная папка имеет приоритет +# над встроенными библиотеками Python. + + +#################################################### +## 6. Классы +#################################################### + +# Мы используем оператор class для создания класса +class Human: + +    # Атрибут класса. Он используется всеми экземплярами этого класса +    species = "Гомосапиенс"      # Обычный конструктор, вызывается при инициализации экземпляра класса      # Обратите внимание, что двойное подчёркивание в начале и в конце имени      # означает объекты и атрибуты, которые используются Python, но находятся      # в пространствах имён, управляемых пользователем. +    # Методы (или объекты или атрибуты), например: +    # __init__, __str__, __repr__ и т. д. называются специальными методами.      # Не придумывайте им имена самостоятельно.      def __init__(self, name): -        # Присваивание значения аргумента атрибуту класса name +        # Присваивание значения аргумента атрибуту          self.name = name +        # Инициализация свойства +        self._age = 0 +      # Метод экземпляра. Все методы принимают self в качестве первого аргумента      def say(self, msg): -       return "%s: %s" % (self.name, msg) +        return "{name}: {message}".format(name=self.name, message=msg) + +    # Другой метод экземпляра +    def sing(self): +        return 'йо... йо... проверка микрофона... раз, два... раз, два...'      # Метод класса разделяется между всеми экземплярами      # Они вызываются с указыванием вызывающего класса в качестве первого аргумента @@ -515,58 +742,242 @@ class Human(object):      def grunt():          return "*grunt*" +    # property похоже на геттер. +    # Оно превращает метод age() в одноименный атрибут только для чтения. +    # Однако нет необходимости писать тривиальные геттеры и сеттеры в Python. +    @property +    def age(self): +        return self._age + +    # Это позволяет установить свойство +    @age.setter +    def age(self, age): +        self._age = age + +    # Это позволяет удалить свойство +    @age.deleter +    def age(self): +        del self._age + + +# Когда интерпретатор Python читает исходный файл, он выполняет весь его код. +# Проверка __name__ гарантирует, что этот блок кода выполняется только тогда, когда +# этот модуль - это основная программа. +if __name__ == '__main__': +    # Инициализация экземпляра класса +    i = Human(name="Иван") +    i.say("привет")                 # Выводит: "Иван: привет" +    j = Human("Пётр") +    j.say("привет")                 # Выводит: "Пётр: привет" +    # i и j являются экземплярами типа Human, или другими словами: они являются объектами Human + +    # Вызов метода класса +    i.say(i.get_species())          # "Иван: Гомосапиенс" +    # Изменение разделяемого атрибута +    Human.species = "Неандертальец" +    i.say(i.get_species())          # => "Иван: Неандертальец" +    j.say(j.get_species())          # => "Пётр: Неандертальец" + +    # Вызов статического метода +    print(Human.grunt())            # => "*grunt*" + +    # Невозможно вызвать статический метод с экземпляром объекта +    # потому что i.grunt() автоматически поместит "self" (объект i) в качестве аргумента +    print(i.grunt())                # => TypeError: grunt() takes 0 positional arguments but 1 was given + +    # Обновить свойство для этого экземпляра +    i.age = 42 +    # Получить свойство +    i.say(i.age)                    # => "Иван: 42" +    j.say(j.age)                    # => "Пётр: 0" +    # Удалить свойство +    del i.age +    # i.age                         # => это выбрасило бы ошибку AttributeError + + +#################################################### +## 6.1 Наследование +#################################################### + +# Наследование позволяет определять новые дочерние классы, которые наследуют методы и +# переменные от своего родительского класса. + +# Используя класс Human, определенный выше как базовый или родительский класс, мы можем +# определить дочерний класс Superhero, который наследует переменные класса, такие как +# "species", "name" и "age", а также методы, такие как "sing" и "grunt" из класса Human, +# но также может иметь свои уникальные свойства. + +# Чтобы воспользоваться преимуществами модульности по файлам, вы можете поместить +# вышеперечисленные классы в их собственные файлы, например, human.py + +# Чтобы импортировать функции из других файлов, используйте следующий формат +# from "имя-файла-без-расширения" import "функция-или-класс" + +from human import Human + + +# Укажите родительский класс(ы) как параметры определения класса +class Superhero(Human): + +    # Если дочерний класс должен наследовать все определения родителя без каких-либо +    # изменений, вы можете просто использовать ключевое слово pass (и ничего больше), +    # но в этом случае оно закомментировано, чтобы разрешить уникальный дочерний класс: +    # pass + +    # Дочерние классы могут переопределять атрибуты своих родителей +    species = 'Сверхчеловек' + +    # Дочерние классы автоматически наследуют конструктор родительского класса, включая +    # его аргументы, но также могут определять дополнительные аргументы или определения +    # и переопределять его методы, такие как конструктор класса. +    # Этот конструктор наследует аргумент "name" от класса "Human" +    # и добавляет аргументы "superpower" и "movie": +    def __init__(self, name, movie=False, +                 superpowers=["сверхсила", "пуленепробиваемость"]): + +        # добавить дополнительные атрибуты класса: +        self.fictional = True +        self.movie = movie +        # помните об изменяемых значениях по умолчанию, +        # поскольку значения по умолчанию являются общими +        self.superpowers = superpowers + +        # Функция "super" позволяет вам получить доступ к методам родительского класса, +        # которые переопределяются дочерним, в данном случае, методом __init__. +        # Это вызывает конструктор родительского класса: +        super().__init__(name) + +    # переопределить метод sing +    def sing(self): +        return 'Бам, бам, БАМ!' + +    # добавить дополнительный метод экземпляра +    def boast(self): +        for power in self.superpowers: +            print("Я обладаю силой '{pow}'!".format(pow=power)) + -# Инициализация экземпляра класса -i = Human(name="Иван") -print(i.say("привет"))     # Выводит: «Иван: привет» +if __name__ == '__main__': +    sup = Superhero(name="Тик") -j = Human("Пётр") -print(j.say("Привет"))  # Выводит: «Пётр: привет» +    # Проверка типа экземпляра +    if isinstance(sup, Human): +        print('Я человек') +    if type(sup) is Superhero: +        print('Я супергерой') -# Вызов метода класса -i.get_species() #=> "H. sapiens" +    # Получить порядок поиска разрешения метода (MRO), +    # используемый как getattr(), так и super() +    # Этот атрибут является динамическим и может быть обновлен +    print(Superhero.__mro__)    # => (<class '__main__.Superhero'>, +                                # => <class 'human.Human'>, <class 'object'>) -# Изменение разделяемого атрибута -Human.species = "H. neanderthalensis" -i.get_species() #=> "H. neanderthalensis" -j.get_species() #=> "H. neanderthalensis" +    # Вызывает родительский метод, но использует свой собственный атрибут класса +    print(sup.get_species())    # => Сверхчеловек -# Вызов статического метода -Human.grunt() #=> "*grunt*" +    # Вызов переопределенного метода +    print(sup.sing())           # => Бам, бам, БАМ! + +    # Вызывает метод из Human +    sup.say('Ложка')            # => Тик: Ложка + +    # Метод вызова, существующий только в Superhero +    sup.boast()                 # => Я обладаю силой 'сверхсила'! +                                # => Я обладаю силой 'пуленепробиваемость'! + +    # Атрибут унаследованного класса +    sup.age = 31 +    print(sup.age)              # => 31 + +    # Атрибут, который существует только в Superhero +    print('Достоин ли я Оскара? ' + str(sup.movie))  #################################################### -## 6. Модули +## 6.2 Множественное наследование  #################################################### -# Вы можете импортировать модули -import math -print(math.sqrt(16)) #=> 4 +# Eще одно определение класса +# bat.py +class Bat: -# Вы можете импортировать отдельные функции модуля -from math import ceil, floor -print(ceil(3.7))  #=> 4.0 -print(floor(3.7)) #=> 3.0 +    species = 'Летучая мышь' -# Можете импортировать все функции модуля. -# (Хотя это и не рекомендуется) -from math import * +    def __init__(self, can_fly=True): +        self.fly = can_fly -# Можете сокращать имена модулей -import math as m -math.sqrt(16) == m.sqrt(16) #=> True -# Вы также можете убедиться, что функции эквивалентны -from math import sqrt -math.sqrt == m.sqrt == sqrt  # => True +    # В этом классе также есть метод say +    def say(self, msg): +        msg = '... ... ...' +        return msg -# Модули в Python — это обычные Python-файлы. Вы -# можете писать свои модули и импортировать их. Название -# модуля совпадает с названием файла. +    # И свой метод тоже +    def sonar(self): +        return '))) ... (((' + +if __name__ == '__main__': +    b = Bat() +    print(b.say('привет')) +    print(b.fly) + + +# И еще одно определение класса, унаследованное от Superhero и Bat +# superhero.py +from superhero import Superhero +from bat import Bat + +# Определите Batman как дочерний класс, унаследованный от Superhero и Bat +class Batman(Superhero, Bat): + +    def __init__(self, *args, **kwargs): +        # Обычно для наследования атрибутов необходимо вызывать super: +        # super(Batman, self).__init__(*args, **kwargs) +        # Однако здесь мы имеем дело с множественным наследованием, а super() +        # работает только со следующим базовым классом в списке MRO. +        # Поэтому вместо этого мы вызываем __init__ для всех родителей. +        # Использование *args и **kwargs обеспечивает чистый способ передачи +        # аргументов, когда каждый родитель "очищает слой луковицы". +        Superhero.__init__(self, 'анонимный', movie=True, +                           superpowers=['Богатый'], *args, **kwargs) +        Bat.__init__(self, *args, can_fly=False, **kwargs) +        # переопределить значение атрибута name +        self.name = 'Грустный Бен Аффлек' + +    def sing(self): +        return 'на на на на на бэтмен!' + + +if __name__ == '__main__': +    sup = Batman() + +    # Получить порядок поиска разрешения метода (MRO), +    # используемый как getattr(), так и super() +    # Этот атрибут является динамическим и может быть обновлен +    print(Batman.__mro__)       # => (<class '__main__.Batman'>, +                                # => <class 'superhero.Superhero'>, +                                # => <class 'human.Human'>, +                                # => <class 'bat.Bat'>, <class 'object'>) + +    # Вызывает родительский метод, но использует свой собственный атрибут класса +    print(sup.get_species())    # => Сверхчеловек + +    # Вызов переопределенного метода +    print(sup.sing())           # => на на на на на бэтмен! + +    # Вызывает метод из Human, потому что порядок наследования имеет значение +    sup.say('Я согласен')          # => Грустный Бен Аффлек: Я согласен + +    # Вызов метода, существующий только во втором родителе +    print(sup.sonar())          # => ))) ... ((( + +    # Атрибут унаследованного класса +    sup.age = 100 +    print(sup.age)              # => 100 + +    # Унаследованный атрибут от второго родителя, +    # значение по умолчанию которого было переопределено. +    print('Могу ли я летать? ' + str(sup.fly)) # => Могу ли я летать? False -# Вы можете узнать, какие функции и атрибуты определены  -# в модуле -import math -dir(math)  ####################################################  ## 7. Дополнительно @@ -577,28 +988,30 @@ def double_numbers(iterable):      for i in iterable:          yield i + i -# Генератор создаёт значения на лету. -# Он не возвращает все значения разом, а создаёт каждое из них при каждой -# итерации.  Это значит, что значения больше 15 в double_numbers -# обработаны не будут. -# Обратите внимание: xrange — это генератор, который делает то же, что и range. -# Создание списка чисел от 1 до 900000000 требует много места и времени. -# xrange создаёт объект генератора, а не список сразу, как это делает range. -# Если нам нужно имя переменной, совпадающее с ключевым словом Python, -# мы используем подчёркивание в конце -xrange_ = xrange(1, 900000000) - -# Будет удваивать все числа, пока результат не превысит 30 -for i in double_numbers(xrange_): +# Генераторы эффективны с точки зрения памяти, потому что они загружают только данные, +# необходимые для обработки следующего значения в итерации. +# Это позволяет им выполнять операции с недопустимо большими диапазонами значений. +# ПРИМЕЧАНИЕ: "range" заменяет "xrange" в Python 3. +for i in double_numbers(range(1, 900000000)):  # "range" - генератор.      print(i)      if i >= 30:          break +# Так же, как вы можете создать интерпретации списков, вы можете создать и +# интерпретации генераторов. +values = (-x for x in [1,2,3,4,5]) +for x in values: +    print(x)  # Выводит -1 -2 -3 -4 -5 + +# Вы также можете преобразовать интерпретацию генератора непосредственно в список. +values = (-x for x in [1,2,3,4,5]) +gen_to_list = list(values) +print(gen_to_list)  # => [-1, -2, -3, -4, -5] +  # Декораторы -# В этом примере beg оборачивает say -# Метод beg вызовет say. Если say_please равно True, -# он изменит возвращаемое сообщение +# В этом примере "beg" оборачивает "say". +# Если say_please равно True, он изменит возвращаемое сообщение.  from functools import wraps @@ -607,7 +1020,7 @@ def beg(target_function):      def wrapper(*args, **kwargs):          msg, say_please = target_function(*args, **kwargs)          if say_please: -            return "{} {}".format(msg, " Пожалуйста! У меня нет денег :(") +            return "{} {}".format(msg, "Пожалуйста! У меня нет денег :(")          return msg      return wrapper @@ -619,8 +1032,8 @@ def say(say_please=False):      return msg, say_please -print(say())  # Вы не купите мне пива? -print(say(say_please=True)) # Вы не купите мне пива? Пожалуйста! У меня нет денег :( +print(say())                 # Вы не купите мне пива? +print(say(say_please=True))  # Вы не купите мне пива? Пожалуйста! У меня нет денег :(  ``` @@ -628,16 +1041,18 @@ print(say(say_please=True)) # Вы не купите мне пива? Пожал  ### Бесплатные онлайн-материалы -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [Официальная документация](http://docs.python.org/2.6/) +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) +* [Официальная документация](http://docs.python.org/3/)  * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) - -### Платные - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) +* [Python Course](http://www.python-course.eu/index.php) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) +* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) +* [Python 3 Computer Science Circles](http://cscircles.cemc.uwaterloo.ca/) +* [Dive Into Python 3](http://www.diveintopython3.net/index.html) +* [A Crash Course in Python for Scientists](http://nbviewer.jupyter.org/gist/anonymous/5924718) +* [Python Tutorial for Intermediates](https://pythonbasics.org/) +* [Build a Desktop App with Python](https://pythonpyqt.com/) diff --git a/ru-ru/python3-ru.html.markdown b/ru-ru/pythonlegacy-ru.html.markdown index 2b6b59a7..ead2af3d 100644 --- a/ru-ru/python3-ru.html.markdown +++ b/ru-ru/pythonlegacy-ru.html.markdown @@ -1,23 +1,23 @@  --- -language: python3 +language: Python 2 (legacy)  lang: ru-ru  contributors:      - ["Louie Dinh", "http://ldinh.ca"] -    - ["Steven Basart", "http://github.com/xksteven"]  translators: +    - ["Yury Timofeev", "http://twitter.com/gagar1n"]      - ["Andre Polykanine", "https://github.com/Oire"] -filename: learnpython3-ru.py +filename: learnpythonlegacy-ru.py  ---  Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из  самых популярных языков. Я влюбился в Python за понятный и доходчивый синтаксис  — это -почти что исполняемый псевдокод. +почти исполняемый псевдокод.  С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh)  или louiedinh [at] [почтовый сервис Google] -Замечание: Эта статья относится только к Python 3. -Если вы хотите изучить Python 2.7, обратитесь к другой статье. +Замечание: Эта статья относится к Python 2.7, но должно работать и в других версиях Python 2.x. +Чтобы изучить Python 3.x, обратитесь к статье по Python 3.  ```python  # Однострочные комментарии начинаются с символа решётки. @@ -37,9 +37,16 @@ filename: learnpython3-ru.py  1 + 1 #=> 2  8 - 1 #=> 7  10 * 2 #=> 20 +35 / 5 #=> 7 -# Кроме деления, которое по умолчанию возвращает число с плавающей запятой -35 / 5  # => 7.0 +# А вот деление немного сложнее. В этом случае происходит деление  +# целых чисел, и результат автоматически округляется в меньшую сторону. +5 / 2 #=> 2 + +# Чтобы делить правильно, сначала нужно немного узнать о числах +# с плавающей запятой. +2.0     # Это число с плавающей запятой +11.0 / 4.0 #=> 2.75 Вооот... Так гораздо лучше  # Результат целочисленного деления округляется в меньшую сторону  # как для положительных, так и для отрицательных чисел. @@ -48,10 +55,6 @@ filename: learnpython3-ru.py  -5 // 3  # => -2  -5.0 // 3.0 # => -2.0 -# Когда вы используете числа с плавающей запятой,  -# результатом будет также число с плавающей запятой -3 * 2.0 # => 6.0 -  # Остаток от деления  7 % 3 # => 1 @@ -61,14 +64,6 @@ filename: learnpython3-ru.py  # Приоритет операций указывается скобками  (1 + 3) * 2 #=> 8 -# Для логических (булевых) значений существует отдельный примитивный тип -True -False - -# Для отрицания используется ключевое слово not -not True #=> False -not False #=> True -  # Логические операторы  # Обратите внимание: ключевые слова «and» и «or» чувствительны к регистру букв  True and False #=> False @@ -81,6 +76,10 @@ False or True #=> True  2 == True #=> False  1 == True #=> True +# Для отрицания используется ключевое слово not +not True #=> False +not False #=> True +  # Равенство — это ==  1 == 1 #=> True  2 == 1 #=> False @@ -95,7 +94,7 @@ False or True #=> True  2 <= 2 #=> True  2 >= 2 #=> True -# Сравнения могут быть записаны цепочкой: +# Сравнения могут быть записаны цепочкой!  1 < 2 < 3 #=> True  2 < 3 < 2 #=> False @@ -103,67 +102,75 @@ False or True #=> True  "Это строка."  'Это тоже строка.' -# И строки тоже могут складываться! Хотя лучше не злоупотребляйте этим. +# И строки тоже можно складывать!  "Привет " + "мир!" #=> "Привет мир!" +# ... или умножать +"Привет" * 3  # => "ПриветПриветПривет" +  # Со строкой можно работать, как со списком символов  "Это строка"[0] #=> 'Э' -# Метод format используется для форматирования строк: +# Символ % используется для форматирования строк, например: +"%s могут быть %s" % ("строки", "интерполированы") + +# Новый способ форматирования строк — использование метода format. +# Это предпочитаемый способ.  "{0} могут быть {1}".format("строки", "форматированы") -# Вы можете повторять аргументы форматирования, чтобы меньше печатать. -"Ехал {0} через реку, видит {0} - в реке {1}! Сунул {0} руку в реку, {1} за руку греку цап!".format("грека", "рак") -#=> "Ехал грека через реку, видит грека - в реке рак! Сунул грека руку в реку, рак за руку греку цап!"  # Если вы не хотите считать, можете использовать ключевые слова.  "{name} хочет есть {food}".format(name="Боб", food="лазанью") -# Если ваш код на Python 3 нужно запускать также и под Python 2.5 и ниже, -# вы также можете использовать старый способ форматирования: -"%s можно %s %s способом" % ("строки", "интерполировать", "старым") -  # None является объектом  None #=> None -# Не используйте оператор равенства '==' для сравнения  -# объектов с None. Используйте для этого 'is' +# Не используйте оператор равенства '=='' для сравнения  +# объектов с None. Используйте для этого «is»  "etc" is None #=> False  None is None  #=> True -# Оператор «is» проверяет идентичность объектов. Он не  +# Оператор 'is' проверяет идентичность объектов. Он не   # очень полезен при работе с примитивными типами, но   # зато просто незаменим при работе с объектами. -# None, 0 и пустые строки/списки/словари приводятся к False. +# None, 0 и пустые строки/списки равны False.  # Все остальные значения равны True -bool(0)  # => False -bool("")  # => False -bool([]) #=> False -bool({}) #=> False +0 == False  #=> True +"" == False #=> True  ####################################################  ## 2. Переменные и коллекции  #################################################### -# В Python есть функция Print -print("Я Python. Приятно познакомиться!") +# В Python есть оператор print, доступный в версиях 2.x, но удалённый в версии 3 +print "Я Python. Приятно познакомиться!" +# В Python также есть функция print(), доступная в версиях 2.7 и 3, +# Но для версии 2.7 нужно добавить следующий импорт модуля (раскомментируйте)): +# from __future__ import print_function +print("Я тоже Python! ")  # Объявлять переменные перед инициализацией не нужно. -# По соглашению используется нижний_регистр_с_подчёркиваниями -some_var = 5 +some_var = 5    # По соглашению используется нижний_регистр_с_подчёркиваниями  some_var #=> 5  # При попытке доступа к неинициализированной переменной  # выбрасывается исключение. -# Об исключениях см. раздел «Поток управления и итерируемые объекты». -some_unknown_var  # Выбрасывает ошибку именования +# См. раздел «Поток управления» для информации об исключениях. +some_other_var  # Выбрасывает ошибку именования + +# if может быть использован как выражение +"yahoo!" if 3 > 2 else 2 #=> "yahoo!"  # Списки хранят последовательности  li = []  # Можно сразу начать с заполненного списка  other_li = [4, 5, 6] +# строка разделена в список +a="adambard" +list(a) #=> ['a','d','a','m','b','a','r','d'] +  # Объекты добавляются в конец списка методом append  li.append(1)    # [1]  li.append(2)    # [1, 2] @@ -176,6 +183,10 @@ li.append(3)    # [1, 2, 4, 3].  # Обращайтесь со списком, как с обычным массивом  li[0] #=> 1 +# Присваивайте новые значения уже инициализированным индексам с помощью = +li[0] = 42 +li[0]  # => 42 +li[0] = 1  # Обратите внимание: возвращаемся на исходное значение  # Обратимся к последнему элементу  li[-1] #=> 3 @@ -197,11 +208,11 @@ li[::-1]   # => [3, 4, 2, 1]  # li[начало:конец:шаг]  # Удаляем произвольные элементы из списка оператором del -del li[2] # [1, 2, 3] +del li[2] # li теперь [1, 2, 3]  # Вы можете складывать, или, как ещё говорят, конкатенировать списки -# Обратите внимание: значения li и other_li при этом не изменились.  li + other_li #=> [1, 2, 3, 4, 5, 6]  — Замечание: li и other_li не изменяются +# Обратите внимание: значения li и other_li при этом не изменились.  # Объединять списки можно методом extend  li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6] @@ -231,7 +242,6 @@ d, e, f = 4, 5, 6  # Обратите внимание, как легко поменять местами значения двух переменных  e, d = d, e     # теперь d == 5, а e == 4 -  #  Словари содержат ассоциативные массивы  empty_dict = {}  # Вот так описывается предзаполненный словарь @@ -241,17 +251,13 @@ filled_dict = {"one": 1, "two": 2, "three": 3}  # что индекс — у словарей он называется ключом — не обязан быть числом  filled_dict["one"] #=> 1 -# Все ключи в виде списка получаются с помощью метода keys().  -# Его вызов нужно обернуть в list(), так как обратно мы получаем -# итерируемый объект, о которых поговорим позднее. -list(filled_dict.keys())   # => ["three", "two", "one"] +# Можно получить все ключи в виде списка с помощью метода keys +filled_dict.keys() #=> ["three", "two", "one"]  # Замечание: сохранение порядка ключей в словаре не гарантируется  # Ваши результаты могут не совпадать с этими. -# Все значения в виде списка можно получить с помощью values(). -# И снова нам нужно обернуть вызов в list(), чтобы превратить -# итерируемый объект в список. -list(filled_dict.values())   # => [3, 2, 1] +# Можно получить и все значения в виде списка, используйте метод values +filled_dict.values() #=> [3, 2, 1]  # То же самое замечание насчёт порядка ключей справедливо и здесь  # При помощи оператора in можно проверять ключи на вхождение в словарь @@ -268,27 +274,28 @@ filled_dict.get("four") #=> None  # возвращено при отсутствии указанного ключа  filled_dict.get("one", 4) #=> 1  filled_dict.get("four", 4) #=> 4 +# Обратите внимание, что filled_dict.get("four") всё ещё => None +# (get не устанавливает значение элемента словаря) -# Метод setdefault вставляет пару ключ-значение, только если такого ключа нет +# Присваивайте значение ключам так же, как и в списках +filled_dict["four"] = 4  # теперь filled_dict["four"] => 4 + +# Метод setdefault() вставляет пару ключ-значение, только если такого ключа нет  filled_dict.setdefault("five", 5) #filled_dict["five"] возвращает 5  filled_dict.setdefault("five", 6) #filled_dict["five"] по-прежнему возвращает 5 -# Добавление элементов в словарь -filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4} -#filled_dict["four"] = 4  # Другой способ добавления элементов - -# Удаляйте ключи из словаря с помощью оператора del -del filled_dict["one"]  # Удаляет ключ «one» из словаря -  # Множества содержат... ну, в общем, множества +# (которые похожи на списки, только в них не может быть дублирующихся элементов)  empty_set = set() -# Инициализация множества набором значений. -# Да, оно выглядит примерно как словарь… ну извините, так уж вышло. -filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} +# Инициализация множества набором значений +some_set = set([1,2,2,3,4]) # some_set теперь равно set([1, 2, 3, 4]) + +# Порядок сортировки не гарантируется, хотя иногда они выглядят отсортированными +another_set = set([4, 3, 2, 2, 1])  # another_set теперь set([1, 2, 3, 4]) -# Множеству можно назначать новую переменную -filled_set = some_set +# Начиная с Python 2.7, вы можете использовать {}, чтобы объявить множество +filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4}  # Добавление новых элементов в множество  filled_set.add(5) # filled_set равно {1, 2, 3, 4, 5} @@ -309,7 +316,7 @@ filled_set | other_set #=> {1, 2, 3, 4, 5, 6}  #################################################### -## 3. Поток управления и итерируемые объекты +## 3. Поток управления  ####################################################  # Для начала заведём переменную @@ -325,13 +332,17 @@ else:           # Это тоже необязательно.      print("some_var равно 10.") -# Циклы For проходят по спискам. Результат: -    # собака — это млекопитающее -    # кошка — это млекопитающее -    # мышь — это млекопитающее +""" +Циклы For проходят по спискам + +Результат: +    собака — это млекопитающее +    кошка — это млекопитающее +    мышь — это млекопитающее +"""  for animal in ["собака", "кошка", "мышь"]: -    # Можете использовать format() для интерполяции форматированных строк -    print("{} — это млекопитающее".format(animal)) +    # Можете использовать оператор % для интерполяции форматированных строк +    print("%s — это млекопитающее" % animal)  """  «range(число)» возвращает список чисел @@ -359,6 +370,8 @@ while x < 4:      x += 1  # Краткая запись для x = x + 1  # Обрабатывайте исключения блоками try/except + +# Работает в Python 2.6 и выше:  try:      # Чтобы выбросить ошибку, используется raise      raise IndexError("Это ошибка индекса") @@ -371,37 +384,6 @@ except (TypeError, NameError):  else:   # Необязательное выражение. Должно следовать за последним блоком except      print("Всё хорошо!")   # Выполнится, только если не было никаких исключений -# Python предоставляет фундаментальную абстракцию, -# которая называется итерируемым объектом (an iterable). -# Итерируемый объект — это объект, который воспринимается как последовательность. -# Объект, который возвратила функция range(), итерируемый. -filled_dict = {"one": 1, "two": 2, "three": 3} -our_iterable = filled_dict.keys() -print(our_iterable) #=> range(1,10). Это объект, реализующий интерфейс iterable - -# Мы можем проходить по нему циклом. -for i in our_iterable: -    print(i)    # Выводит one, two, three - -# Но мы не можем обращаться к элементу по индексу. -our_iterable[1]  # Выбрасывает ошибку типа - -# Итерируемый объект знает, как создавать итератор. -our_iterator = iter(our_iterable) - -# Итератор может запоминать состояние при проходе по объекту. -# Мы получаем следующий объект, вызывая функцию __next__. -our_iterator.__next__()  #=> "one" - -# Он сохраняет состояние при вызове __next__. -our_iterator.__next__()  #=> "two" -our_iterator.__next__()  #=> "three" - -# Возвратив все данные, итератор выбрасывает исключение StopIterator -our_iterator.__next__() # Выбрасывает исключение остановки итератора - -# Вы можете получить сразу все элементы итератора, вызвав на нём функцию list(). -list(filled_dict.keys())  #=> Возвращает ["one", "two", "three"]  #################################################### @@ -419,7 +401,8 @@ add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвр  # Другой способ вызова функции — вызов с именованными аргументами  add(y=6, x=5)   # Именованные аргументы можно указывать в любом порядке. -# Вы можете определить функцию, принимающую переменное число аргументов +# Вы можете определить функцию, принимающую переменное число аргументов, +# которые будут интерпретированы как кортеж, если вы не используете *  def varargs(*args):      return args @@ -427,7 +410,8 @@ varargs(1, 2, 3) #=> (1,2,3)  # А также можете определить функцию, принимающую переменное число -# именованных аргументов +# именованных аргументов, которые будут интерпретированы как словарь, +# если вы не используете **  def keyword_args(**kwargs):      return kwargs @@ -452,6 +436,14 @@ all_the_args(*args) # эквивалентно foo(1, 2, 3, 4)  all_the_args(**kwargs) # эквивалентно foo(a=3, b=4)  all_the_args(*args, **kwargs) # эквивалентно foo(1, 2, 3, 4, a=3, b=4) +# вы можете передавать переменное число позиционных или именованных аргументов +# другим функциям, которые их принимают, распаковывая их с помощью +# * или ** соответственно +def pass_all_the_args(*args, **kwargs): +    all_the_args(*args, **kwargs) +    print varargs(*args) +    print keyword_args(**kwargs) +  # Область определения функций  x = 5 @@ -510,7 +502,7 @@ class Human(object):      # Метод экземпляра. Все методы принимают self в качестве первого аргумента      def say(self, msg): -        return "{name}: {message}".format(name=self.name, message=msg) +       return "%s: %s" % (self.name, msg)      # Метод класса разделяется между всеми экземплярами      # Они вызываются с указыванием вызывающего класса в качестве первого аргумента @@ -563,6 +555,9 @@ from math import *  # Можете сокращать имена модулей  import math as m  math.sqrt(16) == m.sqrt(16) #=> True +# Вы также можете убедиться, что функции эквивалентны +from math import sqrt +math.sqrt == m.sqrt == sqrt  # => True  # Модули в Python — это обычные Python-файлы. Вы  # можете писать свои модули и импортировать их. Название @@ -586,14 +581,15 @@ def double_numbers(iterable):  # Он не возвращает все значения разом, а создаёт каждое из них при каждой  # итерации.  Это значит, что значения больше 15 в double_numbers  # обработаны не будут. -# Обратите внимание: range — это тоже генератор. +# Обратите внимание: xrange — это генератор, который делает то же, что и range.  # Создание списка чисел от 1 до 900000000 требует много места и времени. +# xrange создаёт объект генератора, а не список сразу, как это делает range.  # Если нам нужно имя переменной, совпадающее с ключевым словом Python,  # мы используем подчёркивание в конце -range_ = range(1, 900000000) +xrange_ = xrange(1, 900000000)  # Будет удваивать все числа, пока результат не превысит 30 -for i in double_numbers(range_): +for i in double_numbers(xrange_):      print(i)      if i >= 30:          break @@ -634,10 +630,9 @@ print(say(say_please=True)) # Вы не купите мне пива? Пожал  * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)  * [Dive Into Python](http://www.diveintopython.net/) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) -* [Официальная документация](http://docs.python.org/3/) +* [Официальная документация](http://docs.python.org/2.6/)  * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/3/) +* [Python Module of the Week](http://pymotw.com/2/)  * [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)  ### Платные diff --git a/ru-ru/ruby-ru.html.markdown b/ru-ru/ruby-ru.html.markdown index 69b5fb46..8b263be6 100644 --- a/ru-ru/ruby-ru.html.markdown +++ b/ru-ru/ruby-ru.html.markdown @@ -10,6 +10,7 @@ contributors:    - ["Nick LaMuro", "https://github.com/NickLaMuro"]  translators:    - ["Alexey Makarov", "https://github.com/Anakros"] +  - ["Vasiliy Petrov", "https://github.com/Saugardas"]  ---  ```ruby @@ -35,6 +36,13 @@ translators:  8 - 1 #=> 7  10 * 2 #=> 20  35 / 5 #=> 7 +2**5 #=> 32 +5 % 3 #=> 2 + +# Побитовые операторы +3 & 5 #=> 1 +3 | 5 #=> 7 +3 ^ 5 #=> 6  # Арифметика -- это синтаксический сахар  # над вызовом метода для объекта @@ -57,8 +65,6 @@ false.class #=> FalseClass  # Операция неравенства  1 != 1 #=> false  2 != 1 #=> true -!true  #=> false -!false #=> true  # nil -- имеет такое же логическое значение, как и false @@ -72,6 +78,26 @@ false.class #=> FalseClass  2 <= 2 #=> true  2 >= 2 #=> true +# Оператор сравнения <=> +1 <=> 10 #=> -1 +10 <=> 1 #=> 1 +1 <=> 1 #=> 0 + +# Булевы операторы +true && false #=> false +true || false #=> true +!true #=> false + +# Существуют альтернативные версии логических операторов с гораздо меньшим +# приоритетом. Они используются для связывания операций, пока одна из них +# не вернёт false или true + +# `do_something_else` будет вызван если `do_something` вернёт истинное значение +do_something() and do_something_else() +# `log_error` будет вызван если `do_something` вернёт (nil/false) +do_something() or log_error() + +  # Строки -- это объекты  'Я строка'.class #=> String @@ -82,6 +108,16 @@ placeholder = "использовать интерполяцию строк"  #=> "Я могу использовать интерполяцию строк,  # когда создаю строку с двойными кавычками" +# Конкатенация строк +'hello ' + 'world' #=> "hello world" +'hello ' + 3 #=> TypeError: can't convert Fixnum into String +'hello ' + 3.to_s #=> "hello 3" + +# Умножение строк +'hello ' * 3 #=> "hello hello hello " + +# Добавление к строке +'hello' << ' world' #=> "hello world"  # печатать в стандартный вывод  puts "Я печатаюсь!" @@ -134,6 +170,7 @@ array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]  # Значение в массиве можно получить по индексу с левой границы  array[0] #=> 1 +array.first #=> 1  array[12] #=> nil  # Как и арифметика, доступ к значению в массиве @@ -143,15 +180,26 @@ array.[] 12 #=> nil  # Также, можно получить по индексу с правой границы  array[-1] #=> 5 +array.last #=> 5 -# С заданными левой и правой границами индексов -array[2, 4] #=> [3, 4, 5] +# Задавая индекс и количество элементов +array[0,2] #=> [1, 2] +array[0,999] #=> [1, 2, 3, 4, 5]  # Или с использованием диапазона значений  array[1..3] #=> [2, 3, 4] +# Перестановка элементов в обратном порядке +a = [1, 2, 3] +a.reverse #=> [3, 2, 1] +  # Вот так можно добавить значение в массив  array << 6 #=> [1, 2, 3, 4, 5, 6] +# Или так +array.push(6) #=> [1, 2, 3, 4, 5, 6] + +# Проверка включения элемента в массив +array.include?(1) #=> true  # Хэши -- это массив пар "ключ => значение".  # Хэши объявляются с использованием фигурных скобок: @@ -174,19 +222,33 @@ new_hash = { defcon: 3, action: true}  new_hash.keys #=> [:defcon, :action] +# Проверка существования ключа и значения в хеше +new_hash.key?(:defcon) #=> true +new_hash.value?(3) #=> true +  # Массивы и Хэши -- перечисляемые типы данных  # У них есть много полезных методов, например: each, map, count и другие  # Управление ходом выполнения (Управляющие структуры) +# Условия  if true -  "Если истина" +  'Если истина'  elsif false -  "Иначе, если ложь (опционально)" +  'Иначе, если ложь (опционально)'  else -  "Во всех других случаях" +  'Во всех других случаях (тоже опционально)'  end +# Если условие контролирует выполнение не блока кода, а единственного выражения, +# можно использовать постфиксную запись условного оператора +warnings = ['Отсутствует отчество', 'Слишком короткий адрес'] +puts("Обратите внимание:\n" + warnings.join("\n"))  if !warnings.empty? + +# Иногда условие лучше звучит с `unless`, чем с `if` +puts("Обратите внимание:\n" + warnings.join("\n"))  unless warnings.empty? + +# Циклы  for counter in 1..5    puts "итерация #{counter}"  end @@ -220,7 +282,7 @@ end  #=> итерация 5  # Вы также можете ограничивать блоки фигурными скобками: -(1..5).each {|counter| puts "итерация #{counter}"} +(1..5).each { |counter| puts "итерация #{counter}" }  # Содержимое структурных данных также можно перебирать используя "each":  array.each do |element| @@ -230,6 +292,21 @@ hash.each do |key, value|    puts "#{key} -- это #{value}"  end +# Если вам нужен индекс вы можете использовать "each_with_index" +# В этом случае индекс будет начинаться с 0 +array.each_with_index do |element, index| +  puts "#{element} is number #{index} in the array" +end + +# Если индекс должен начинаться с произвольного значения, +# используйте "each.with_index" +[:q, :w, :e].each.with_index(100) do |element, index| +  puts "#{element} -> #{index}" +end +#=> :q -> 100 +#=> :w -> 101 +#=> :e -> 102 +  counter = 1  while counter <= 5 do    puts "итерация #{counter}" @@ -241,22 +318,65 @@ end  #=> итерация 4  #=> итерация 5 +# Существует большое количество других полезных функций, +# например "map", "reduce", "inject", и так далее. Например, "map" +# выполняет связанный с ним блок для каждого элемента перечисляемого объекта, +# возвращая массив результатов. +array = [1, 2, 3, 4, 5] +doubled = array.map do |element| +  element * 2 +end +puts doubled +#=> [2, 4, 6, 8, 10] +puts array +#=> [1, 2, 3, 4, 5] +  grade = 'B'  case grade  when 'A' -  puts "Так держать, детка!" +  puts 'Так держать, детка!'  when 'B' -  puts "Тебе повезёт в следующий раз" +  puts 'Тебе повезёт в следующий раз'  when 'C' -  puts "Ты можешь сделать лучше" +  puts 'Ты можешь сделать лучше'  when 'D' -  puts "Выскоблил последнее" +  puts 'Выскоблил последнее'  when 'F' -  puts "Ты провалился!" +  puts 'Ты провалился!'  else -  puts "Альтернативная система оценок, да?" +  puts 'Альтернативная система оценок, да?'  end +#=> 'Тебе повезёт в следующий раз' + +# в when также можно использовать диапазоны +grade = 82 +case grade +when 90..100 +  puts 'Ура!' +when 80...90 +  puts 'Хорошая работа!' +else +  puts 'Вы не справились!' +end +#=> 'Хорошая работа!' + +# Обработка исключений +begin +  # здесь код, который может вызвать исключение +  raise NoMemoryError, 'У вас закончилась память.' +rescue NoMemoryError => exception_variable +  puts 'Был вызван NoMemoryError', exception_variable +rescue RuntimeError => other_exception_variable +  puts 'Был вызван RuntimeError' +else +  puts 'Этот код будет выполнятся, если исключения не были вызваны' +ensure +  puts 'Этот код выполняется всегда' +end +#=> Был вызван NoMemoryError +#=> У вас закончилась память. +#=> Этот код выполняется всегда  # Функции @@ -298,6 +418,43 @@ surround { puts 'hello world' }  # } +# Вы можете передать блок методу +# "&" отмечает ссылку на переданный блок +def guests(&block) +  block.call 'some_argument' +end + +# Чтобы метод принимал произвольное количество аргументов, спереди +# одного из параметров ставится префикс "*" +def method(first, *rest) +  p rest +end +method(1, 2, 3, 4) #=> [2, 3, 4] + +# Если метод возвращает массив. можно использовать множественное присваивание +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.upcase #=> "DUNDER MIFFLIN" +company_name #=> "Dunder Mifflin" +company_name.upcase! # Изменяем зачение company_name! +company_name #=> "DUNDER MIFFLIN" + +  # Определение класса с помощью ключевого слова "class"  class Human @@ -323,6 +480,13 @@ class Human      @name    end +  # Тоже самое можно определить с помощью attr_accessor +  attr_accessor :name + +  # Также можно создать методы только для записи или чтения +  attr_reader :name +  attr_writer :name +    # Метод класса определяется с ключевым словом "self",    # чтобы можно было отличить его от метода экземпляра класса.    # Он может быть вызван только на уровне класса, но не экземпляра. diff --git a/ru-ru/rust-ru.html.markdown b/ru-ru/rust-ru.html.markdown new file mode 100644 index 00000000..9293a40e --- /dev/null +++ b/ru-ru/rust-ru.html.markdown @@ -0,0 +1,313 @@ +--- +language: rust + +filename: learnrust-ru.rs +contributors: +    - ["P1start", "http://p1start.github.io/"] +translators: +    - ["Anatolii Kosorukov", "https://github.com/java1cprog"] +    - ["Vasily Starostin", "https://github.com/Basil22"] +lang: ru-ru + +--- + +Язык Rust разработан в Mozilla Research. Он сочетает низкоуровневую производительность с удобством языка высокого уровня и одновременно гарантирует безопасность памяти. + +Он достигает этих целей без сборщика мусора или сложной среды выполнения, что позволяет использовать библиотеки Rust как прямую замену +C-библиотек. И наоборот, Rust умеет использовать готовые С-библиотеки как есть, без накладных расходов. + +Первый выпуск Rust, 0.1, произошел в январе 2012 года. В течение 3 лет развитие продвигалось настолько быстро, что язык серьезно менялся без сохранения совместимости. Это дало возможность обкатать и отполировать синтаксис и возможности языка. + +15 мая 2015 года был выпущен Rust 1.0 с полной гарантией обратной совместимости. Сборка поставляется в трех вариантах: стабильная версия, бета-версия, ночная версия. Все нововведения языка сперва обкатываются на ночной и бета-версиях, и только потом попадают в стабильную. Выход очередной версии происходит раз в 6 недель. В 2018 году вышло второе большое обновление языка, добавившее ему новых возможностей. + +Хотя 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 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; + +    // Перечисление с полями +    // В отличие от C и C++ компилятор автоматически следит за тем, +    // какой именно тип хранится в перечислении. +    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/sql-ru.html.markdown b/ru-ru/sql-ru.html.markdown new file mode 100644 index 00000000..7353a175 --- /dev/null +++ b/ru-ru/sql-ru.html.markdown @@ -0,0 +1,120 @@ +--- +language: SQL +filename: learnsql-ru.sql +contributors: +  - ["Bob DuCharme", "http://bobdc.com/"] +translators: +  - ["Shaltaev", "https://github.com/shaltaev"] +  - ["Andre Polykanine", "https://github.com/Menelion"] +lang: ru-ru +--- + +Язык структурированных запросов (SQL) — это стандартный язык ISO для создания +и работы с базами данных, хранящимися в наборе таблиц. Реализации обычно +добавляют свои собственные расширения к языку; +[Сравнение различных реализаций SQL](http://troels.arvin.dk/db/rdbms/) — хороший справочник по различиям в продуктах. + +Реализации обычно предоставляют приглашение командной строки, где вы можете +вводить команды, описанные ниже, в интерактивном режиме, также есть способ +выполнить серию таких команд, сохранённых в файле скрипта. +(Результат того, что вы сделали с помощью интерактивного режима, является +хорошим примером того, что не стандартизировано, — большинство реализаций SQL +поддерживают ключевые слова QUIT, EXIT или оба). + +Некоторые команды ниже предполагают использование +[демонстрационного образца базы данных сотрудников от MySQL](https://dev.mysql.com/doc/employee/en/), доступного на [Github](https://github.com/datacharmer/test_db). +Следовательно, для повторения команд в локальном окружении он должен быть загружен. +Файлы на github — это скрипты с командами, которые схожи с командами ниже, +которые создают и манипулируют таблицами и данными о сотрудниках вымышленной +компании. Синтаксис для запуска этих скриптов будет зависеть от используемой +вами реализации SQL. Обычно используется утилита, запускаемая из командной +строки в вашей операционной системе. + +```sql +-- Комментарии начинаются с двух дефисов. Завершайте каждую команду +-- точкой с запятой. + +-- SQL не учитывает регистр букв для ключевых слов. Примеры команд здесь +-- следуют соглашению о написании в верхнем регистре, потому что +-- это позволяет легче отличить их от имён баз, таблиц и колонок. + +-- Создание и удаление базы данных. Имена базы и таблицы чувствительны +-- к регистру букв. +CREATE DATABASE someDatabase; +DROP DATABASE someDatabase; + +-- Список доступных баз. +SHOW DATABASES; + +-- Выбор базы для работы. +USE employees; + +-- Выбрать все строки и колонки из таблицы «departments» (отделы) текущей базы. +-- В интерактивном режиме обыч	но результат будет выведен на экран. +SELECT * FROM departments; + +-- Тот же запрос, что и выше, но выбор только колонок «dept_no» и «dept_name». +-- Разбиение команд на несколько строк допустимо. +SELECT dept_no, +       dept_name FROM departments; + +-- В данном случае будут выбраны все колонки, но только первые 5 строк. +SELECT * FROM departments LIMIT 5; + +-- Выбор названий отделов, содержащих подстроку «en». +SELECT dept_name FROM departments WHERE dept_name LIKE '%en%'; + +-- Выбор всех колонок, где названия отделов начинаются на «S», +-- после которой идёт ровно четыре символа. +SELECT * FROM departments WHERE dept_name LIKE 'S____'; + +-- Выбор всех должностей из таблицы «titles», но без повторений. +SELECT DISTINCT title FROM titles; + +-- В дополнение к предыдущему запросу результат будет отсортирован +-- в алфавитном порядке (с учётом регистра). +SELECT DISTINCT title FROM titles ORDER BY title; + +-- Показать число строк в таблице отделов. +SELECT COUNT(*) FROM departments; + +-- Показать число строк, где название отдела содержит подстроку «en» +SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%'; + +-- Объединение информации из нескольких таблиц: +-- В таблице «titles» перечислены должности, кто их занимал по номеру сотрудника, +-- а также с какой даты по какую. Получим эту информацию, но используем номера +-- сотрудников как ссылку на таблицу «employees», чтобы получить имя и фамилию +-- каждого сотрудника. Выводим только 10 строк. +SELECT employees.first_name, employees.last_name, +       titles.title, titles.from_date, titles.to_date +FROM titles INNER JOIN employees ON +       employees.emp_no = titles.emp_no LIMIT 10; + +-- Список всех таблиц во всех базах. Реализации обычно предоставляют +-- собственные сокращения, чтобы показать все таблицы текущей базы. +SELECT * FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_TYPE='BASE TABLE'; + +-- Создать таблицу с именем tablename1 и двумя колонками в текущей базе. +-- Для колонок имеется множество параметров, таких как тип данных. +CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20)); + +-- Вставляем строку данных в таблицу «tablename1». Предполагаем, что таблица +-- настроена таким образом, чтобы принимать эти значения. +INSERT INTO tablename1 VALUES('Richard','Mutt'); + +-- В таблице «tablename1» изменить значение fname на «John» +-- для каждой строки, где колонка lname равна «Mutt». +UPDATE tablename1 SET fname='John' WHERE lname='Mutt'; + +-- Удалить из таблицы «tablename1» строки, +-- где значение колонки lname начинается с «M». +DELETE FROM tablename1 WHERE lname like 'M%'; + +-- Удалить все строки из таблицы «tablename1». В итоге получим пустую таблицу. +DELETE FROM tablename1; + +-- Удалить таблицу «tablename1» полностью. +DROP TABLE tablename1; +``` diff --git a/ru-ru/swift-ru.html.markdown b/ru-ru/swift-ru.html.markdown index 7ff660e1..f2b1fd36 100644 --- a/ru-ru/swift-ru.html.markdown +++ b/ru-ru/swift-ru.html.markdown @@ -376,14 +376,14 @@ print("Имя :\(name)") // Имя: Яков  // Протокол `Error` используется для перехвата выбрасываемых ошибок  enum MyError: Error { -    case BadValue(msg: String) -    case ReallyBadValue(msg: String) +    case badValue(msg: String) +    case reallyBadValue(msg: String)  }  // фунции помеченные словом `throws` должны вызываться с помощью `try`  func fakeFetch(value: Int) throws -> String {      guard 7 == value else { -        throw MyError.ReallyBadValue(msg: "Действительно плохое значение") +        throw MyError.reallyBadValue(msg: "Действительно плохое значение")      }      return "тест" @@ -401,7 +401,7 @@ func testTryStuff() {      do {          // обычно try оператор, позволяющий обработать ошибку в `catch` блоке          try fakeFetch(value: 1) -    } catch MyError.BadValue(let msg) { +    } catch MyError.badValue(let msg) {          print("Ошибка: \(msg)")      } catch {          // все остальное @@ -535,49 +535,49 @@ if let circle = myEmptyCircle {  // Они могут содержать методы подобно классам.  enum Suit { -    case Spades, Hearts, Diamonds, Clubs +    case spades, hearts, diamonds, clubs      func getIcon() -> String {          switch self { -        case .Spades: return "♤" -        case .Hearts: return "♡" -        case .Diamonds: return "♢" -        case .Clubs: return "♧" +        case .spades: return "♤" +        case .hearts: return "♡" +        case .diamonds: return "♢" +        case .clubs: return "♧"          }      }  }  // Значения перечислений допускают сокращенный синтаксис, нет необходимости  // указывать тип перечисления, когда переменная объявляется явно -var suitValue: Suit = .Hearts +var suitValue: Suit = .hearts  // Значения нецелочисленных перечислений должны быть указаны явно  // или могут выводится с помощью функции `rawValue` из имени  enum BookName: String { -    case John -    case Luke = "Лука" +    case john +    case luke = "Лука"  } -print("Имя: \(BookName.John.rawValue)") +print("Имя: \(BookName.john.rawValue)")  // Перечисление (enum) со связанными значениями  enum Furniture {      // Связать с типом Int -    case Desk(height: Int) +    case desk(height: Int)      // Связать с типами String и Int -    case Chair(String, Int) +    case chair(String, Int)      func description() -> String {          switch self { -        case .Desk(let height): +        case .desk(let height):              return "Письменный стол высотой \(height) см." -        case .Chair(let brand, let height): +        case .chair(let brand, let height):              return "Стул марки \(brand) высотой \(height) см."          }      }  } -var desk: Furniture = .Desk(height: 80) +var desk: Furniture = .desk(height: 80)  print(desk.description())     // "Письменный стол высотой 80 см." -var chair = Furniture.Chair("Foo", 40) +var chair = Furniture.chair("Foo", 40)  print(chair.description())    // "Стул марки Foo высотой 40 см." diff --git a/ru-ru/vim-ru.html.markdown b/ru-ru/vim-ru.html.markdown index 6f62fd49..f43f99eb 100644 --- a/ru-ru/vim-ru.html.markdown +++ b/ru-ru/vim-ru.html.markdown @@ -9,7 +9,7 @@ filename: LearnVim-ru.txt  lang: ru-ru  --- -[Vim](www.vim.org) +[Vim](http://www.vim.org)  (Vi IMproved) это клон полулярного текстового редактора для Unix. Он разработан  с целью повышения скорости и продуктивности и повсеместно используется в   большинство Юникс-подобных систем. В нем имеется множество клавиатурных  diff --git a/ru-ru/yaml-ru.html.markdown b/ru-ru/yaml-ru.html.markdown new file mode 100644 index 00000000..ddaed2b6 --- /dev/null +++ b/ru-ru/yaml-ru.html.markdown @@ -0,0 +1,189 @@ +--- +language: yaml +filename: learnyaml-ru.yaml +contributors: +- [Leigh 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/) | 
