summaryrefslogtreecommitdiffhomepage
path: root/ru-ru
diff options
context:
space:
mode:
Diffstat (limited to 'ru-ru')
-rw-r--r--ru-ru/asymptotic-notation-ru.html.markdown225
-rw-r--r--ru-ru/bash-ru.html.markdown293
-rw-r--r--ru-ru/bf.html.markdown (renamed from ru-ru/brainfuck-ru.html.markdown)5
-rw-r--r--ru-ru/binary-search-ru.html.markdown64
-rw-r--r--ru-ru/c++-ru.html.markdown892
-rw-r--r--ru-ru/c-ru.html.markdown37
-rw-r--r--ru-ru/clojure-ru.html.markdown4
-rw-r--r--ru-ru/css-ru.html.markdown250
-rw-r--r--ru-ru/d-ru.html.markdown754
-rw-r--r--ru-ru/elixir-ru.html.markdown467
-rw-r--r--ru-ru/erlang-ru.html.markdown2
-rw-r--r--ru-ru/forth-ru.html.markdown240
-rw-r--r--ru-ru/go-ru.html.markdown9
-rw-r--r--ru-ru/haml-ru.html.markdown233
-rw-r--r--ru-ru/haskell-ru.html.markdown3
-rw-r--r--ru-ru/html-ru.html.markdown129
-rw-r--r--ru-ru/java-ru.html.markdown51
-rw-r--r--ru-ru/javascript-ru.html.markdown10
-rw-r--r--ru-ru/json-ru.html.markdown61
-rw-r--r--ru-ru/kotlin-ru.html.markdown375
-rw-r--r--ru-ru/lua-ru.html.markdown2
-rw-r--r--ru-ru/markdown-ru.html.markdown300
-rw-r--r--ru-ru/nim-ru.html.markdown279
-rw-r--r--ru-ru/objective-c-ru.html.markdown659
-rw-r--r--ru-ru/paren-ru.html.markdown196
-rw-r--r--ru-ru/perl-ru.html.markdown195
-rw-r--r--ru-ru/php-ru.html.markdown267
-rw-r--r--ru-ru/pyqt-ru.html.markdown86
-rw-r--r--ru-ru/python-ru.html.markdown114
-rw-r--r--ru-ru/python3-ru.html.markdown58
-rw-r--r--ru-ru/qt-ru.html.markdown158
-rw-r--r--ru-ru/ruby-ru.html.markdown183
-rw-r--r--ru-ru/swift-ru.html.markdown699
-rw-r--r--ru-ru/tmux-ru.html.markdown252
-rw-r--r--ru-ru/typescript-ru.html.markdown173
-rw-r--r--ru-ru/vim-ru.html.markdown241
-rw-r--r--ru-ru/xml-ru.html.markdown145
37 files changed, 7752 insertions, 359 deletions
diff --git a/ru-ru/asymptotic-notation-ru.html.markdown b/ru-ru/asymptotic-notation-ru.html.markdown
new file mode 100644
index 00000000..73ad80ba
--- /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://gihub.com/pru-mike"]
+lang: ru-ru
+---
+
+# О-cимволика
+
+## Что это такое?
+
+О-cимволика или асимптотическая запись это система символов позволяющая оценить
+время выполнения алгоритма, устанавливая зависимость времени выполнения от
+увеличения объема входных данных, так же известна как оценка
+сложности алгоритмов. Быстро-ли алгоритм станет невероятно медленным, когда
+объем входных данных увеличится? Будет-ли алгоритм выполняться достаточно быстро,
+если объем входных данных возрастет? О-символика позволяет ответить на эти
+вопросы.
+
+## Можно-ли по-другому найти ответы на эти вопросы?
+
+Один способ это подсчитать число элементарных операций в зависимости от
+различных объемов входных данных. Хотя это и приемлемое решение, тот объем
+работы которого оно потребует, даже для простых алгоритмов, делает его
+использование неоправданным.
+
+Другой способ это измерить какое время алгоритм потребует для завершения на
+различных объемах входных данных. В тоже время, точность и относительность
+(полученное время будет относиться только к той машине на которой оно
+вычислено) этого метода зависит от среды выполнения: компьютерного аппаратного
+обеспечения, мощности процессора и т.д.
+
+## Виды О-символики
+
+В первом разделе этого документа мы определили, что О-символика
+позволяет оценивать алгоритмы в зависимости от изменения размера входных
+данных. Представим что алгоритм это функция f, n размер входных данных и
+f(n) время выполнения. Тогда для данного алгоритма f c размером входных
+данных n получим какое-то результирующее время выполнения f(n).
+Из этого можно построить график, где ось Y время выполнения, ось X размер входных
+данных и точки на графике это время выполнения для заданного размера входных
+данных.
+
+С помощью О-символики можно оценить функцию или алгоритм
+несколькими различными способами. Например можно оценить алгоритм исходя
+из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается
+анализ на основе верхней оценки. Как правило не используется нижняя оценка,
+потому что она не подходит под планируемые условия. Отличный пример алгоритмы
+сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка
+большинства таких алгоритмов может быть дана как одна операция. В то время как в
+большинстве случаев, добавляемые элементы должны быть отсортированы
+соответствующим образом при помощи дерева, что может потребовать обхода целой
+ветви. Это и есть худший случай, для которого планируется верхняя оценка.
+
+### Виды функций, пределы и упрощения
+
+```
+Логарифмическая функция - log n
+Линейная функция - an + b
+Квадратическая функция - an^2 + bn +c
+Полиномиальная функция - an^z + . . . + an^2 + a*n^1 + a*n^0, где z константа
+Экспоненциальная функция - a^n, где a константа
+```
+
+Приведены несколько базовых функций используемых при определении сложности в
+различных оценках. Список начинается с самой медленно возрастающей функции
+(логарифм, наиболее быстрое время выполнения) и следует до самой быстро
+возрастающей функции (экспонента, самое медленное время выполнения). Отметим,
+что в то время как 'n' или размер входных данных, возрастает в каждой из этих функций,
+результат намного быстрее возрастает в квадратической, полиномиальной
+и экспоненциальной по сравнению с логарифмической и линейной.
+
+Крайне важно понимать, что при использовании описанной далее нотации необходимо
+использовать упрощенные выражения.
+Это означает, что необходимо отбрасывать константы и слагаемые младших порядков,
+потому что если размер входных данных (n в функции f(n) нашего примера)
+увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков
+и константы становятся пренебрежительно малыми. Таким образом, если есть
+константа например размера 2^9001 или любого другого невообразимого размера,
+надо понимать, что её упрощение внесёт значительные искажения в точность
+оценки.
+
+Т.к. нам нужны упрощенные выражения, немного скорректируем нашу таблицу...
+
+```
+Логарифм - log n
+Линейная функция - n
+Квадратическая функция - n^2
+Полиномиальная функция - n^z, где z константа
+Экспонента - a^n, где a константа
+```
+
+### О-Большое
+О-Большое, записывается как **О**, это асимптотическая запись для оценки худшего
+случая или для ограничения заданой функции сверху. Это позволяет сделать
+_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения
+алгоритма. Допустим `f(n)` время выполнения алгоритма и `g(n)` заданная временная
+сложность которая проверяется для алгоритма. Тогда `f(n)` это O(g(n)), если
+существуют действительные константы с (с > 0) и n<sub>0</sub>, такие
+что `f(n)` <= `c g(n)` выполняется для всех n начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>).
+
+*Пример 1*
+
+```
+f(n) = 3log n + 100
+g(n) = log n
+```
+
+Является-ли `f(n)` O(g(n))?
+Является-ли `3 log n + 100` O(log n)?
+Посмотрим на определение О-Большого:
+
+```
+3log n + 100 <= c * log n
+```
+
+Существуют-ли константы c, n<sub>0</sub> такие что выражение верно для всех n > n<sub>0</sub>
+
+```
+3log n + 100 <= 150 * log n, n > 2 (неопределенно для n = 1)
+```
+
+Да! По определению О-Большого `f(n)` является O(g(n)).
+
+*Пример 2*
+
+```
+f(n) = 3 * n^2
+g(n) = n
+```
+
+Является-ли `f(n)` O(g(n))?
+Является-ли `3 * n^2` O(n)?
+Посмотрим на определение О-Большого:
+
+```
+3 * n^2 <= c * n
+```
+
+Существуют-ли константы c, n<sub>0</sub> такие что выражение верно для всех n > n<sub>0</sub>?
+Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)).
+
+### Омега-Большое
+Омега-Большое, записывается как **Ω**, это асимптотическая запись для оценки
+лучшего случая или для ограничения заданой функции снизу. Это позволяет сделать
+_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения
+алгоритма.
+
+`f(n)` принадлежит Ω(g(n)), если существуют действительные константы
+с (с > 0) и <sub>0</sub> (n<sub>0</sub> > 0), такие что `f(n)` >= `c g(n)` для всех n > n<sub>0</sub>.
+
+### Примечание
+
+Асимптотические оценки сделаные при помощи О-Большое и Омега-Большое могут
+как быть так и не быть точными. Для того что бы обозначить что границы не
+являются асимптотически точными используются записи о-малое и омега-малое.
+
+### О-Малое
+O-Малое, записывается как **о**, это асимптотическая запись для оценки верхней
+границы времени выполнения алгоритма, при условии что граница не является
+асимптотически точной.
+
+`f(n)` является o(g(n)), если можно подобрать такие действительные константы,
+что для всех c (c > 0) найдется n<sub>0</sub> (n<sub>0</sub> > 0), так
+что `f(n)` < `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
+
+Определения О-символики для О-Большое и О-Малое похожи. Главное отличие в том,
+что если f(n) = O(g(n)), тогда условие f(n) <= c g(n) выполняется если _**существует**_
+константа c > 0, но если f(n) = o(g(n)), тогда условие f(n) < c g(n) выполняется
+для _**всех**_ констант с > 0.
+
+### Омега-малое
+Омега-малое, записывается как **ω**, это асимптотическая запись для оценки
+верней границы времени выполнения алгоритма, при условии что граница не является
+асимптотически точной.
+
+`f(n)` является ω(g(n)), если можно подобрать такие действительные константы,
+что для всех c (c > 0) найдется n<sub>0</sub> (n<sub>0</sub> > 0), так
+что `f(n)` > `c g(n)` выполняется для всех n (n > n<sub>0</sub>)
+
+Определения Ω-символики и ω-символики похожи. Главное отличие в том, что
+если f(n) = Ω(g(n)), тогда условие f(n) >= c g(n) выполняется если _**существует**_
+константа c > 0, но если f(n) = ω(g(n)), тогда условие f(n) > c g(n)
+выполняется для _**всех**_ констант с > 0.
+
+### Тета
+Тета, записывается как **Θ**, это асимптотическая запись для оценки
+_***асимптотически точной границы***_ времени выполнения алгоритма.
+
+`f(n)` является Θ(g(n)), если для некоторых действительных
+констант c1, c2 и n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0),
+`c1 g(n)` < `f(n)` < `c2 g(n)` для всех n (n > n<sub>0</sub>).
+
+∴ `f(n)` является Θ(g(n)) означает что `f(n)` является O(g(n))
+и `f(n)` является Ω(g(n)).
+
+О-Большое основной инструмент для анализа сложности алгоритмов.
+Так же смотрите примеры по ссылкам.
+
+### Заключение
+Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и
+посмотреть дополнительную литературу. В них дается более глубокое описание с
+определениями и примерами.
+
+
+## Дополнительная литература
+
+* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/)
+* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/)
+
+## Ссылки
+
+* [Оценки времени исполнения. Cимвол O()](http://algolist.manual.ru/misc/o_n.php)
+* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903)
+
+## Ссылки (Eng)
+
+* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1)
+* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf)
+* [Cheatsheet 2](http://bigocheatsheet.com/)
+
diff --git a/ru-ru/bash-ru.html.markdown b/ru-ru/bash-ru.html.markdown
new file mode 100644
index 00000000..5e99afc2
--- /dev/null
+++ b/ru-ru/bash-ru.html.markdown
@@ -0,0 +1,293 @@
+---
+category: tool
+tool: bash
+contributors:
+ - ["Max Yankov", "https://github.com/golergka"]
+ - ["Darren Lin", "https://github.com/CogBear"]
+ - ["Alexandre Medeiros", "http://alemedeiros.sdf.org"]
+ - ["Denis Arh", "https://github.com/darh"]
+ - ["akirahirose", "https://twitter.com/akirahirose"]
+ - ["Anton Strömkvist", "http://lutic.org/"]
+ - ["Rahil Momin", "https://github.com/iamrahil"]
+ - ["Gregrory Kielian", "https://github.com/gskielian"]
+ - ["Etan Reisner", "https://github.com/deryni"]
+translators:
+ - ["Andrey Samsonov", "https://github.com/kryzhovnik"]
+ - ["Andre Polykanine", "https://github.com/Oire"]
+filename: LearnBash-ru.sh
+lang: ru-ru
+---
+
+Bash - это командная оболочка unix (unix shell), которая распространялась как оболочка для операционной системы 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 - тоже комментарий.
+
+# Простой пример hello world:
+echo Hello world!
+
+# Отдельные команды начинаются с новой строки или разделяются точкой с запятой:
+echo 'Это первая строка'; echo 'Это вторая строка'
+
+# Вот так объявляется переменная:
+VARIABLE="Просто строка"
+
+# но не так:
+VARIABLE = "Просто строка"
+# Bash решит, что VARIABLE - это команда, которую он должен исполнить,
+# и выдаст ошибку, потому что не сможет найти ее.
+
+# и не так:
+VARIABLE= 'Просто строка'
+# Тут Bash решит, что 'Просто строка' - это команда, которую он должен исполнить,
+# и выдаст ошибку, потому что не сможет найти такой команды
+# (здесь 'VARIABLE=' выглядит как присвоение значения переменной,
+# но только в контексте исполнения команды 'Просто строка').
+
+# Использование переменой:
+echo $VARIABLE
+echo "$VARIABLE"
+echo '$VARIABLE'
+# Когда вы используете переменную - присваиваете, экспортируете и т.д. -
+# пишите её имя без $. А для получения значения переменной используйте $.
+# Заметьте, что ' (одинарные кавычки) не раскрывают переменные в них.
+
+# Подстановка строк в переменные
+echo ${VARIABLE/Просто/A}
+# Это выражение заменит первую встреченную подстроку "Просто" на "A"
+
+# Взять подстроку из переменной
+LENGTH=7
+echo ${VARIABLE:0:LENGTH}
+# Это выражение вернет только первые 7 символов переменной VARIABLE
+
+# Значение по умолчанию
+echo ${FOO:-"DefaultValueIfFOOIsMissingOrEmpty"}
+# Это сработает при отсутствующем значении (FOO=) и пустой строке (FOO="");
+# ноль (FOO=0) вернет 0.
+# Заметьте, что в любом случае значение самой переменной FOO не изменится.
+
+# Встроенные переменные:
+# В bash есть полезные встроенные переменные, например
+echo "Последнее возвращенное значение: $?"
+echo "PID скрипта: $$"
+echo "Количество аргументов: $#"
+echo "Аргументы скрипта: $@"
+echo "Аргументы скрипта, распределённые по отдельным переменным: $1 $2..."
+
+# Чтение аргументов из устройста ввода:
+echo "Как Вас зовут?"
+read NAME # Обратите внимание, что нам не нужно определять новую переменную
+echo Привет, $NAME!
+
+# У нас есть обычная структура if:
+# наберите 'man test' для получения подробной информации о форматах условия
+if [ $NAME -ne $USER ]
+then
+ echo "Имя не совпадает с именем пользователя"
+else
+ echo "Имя совпадает с именем пользователя"
+fi
+
+# Примечание: если $Name пустой, bash интерпретирует код как:
+if [ -ne $USER ]
+# а это ошибочная команда
+# поэтому такие переменные нужно использовать так:
+if [ "$Name" -ne $USER ] ...
+# когда $Name пустой, bash видит код как:
+if [ "" -ne $USER ] ...
+# что работает правильно
+
+# Также есть условное исполнение
+echo "Исполнится всегда" || echo "Исполнится, если первая команда завершится ошибкой"
+echo "Исполнится всегда" && echo "Исполнится, если первая команда выполнится удачно"
+
+# Можно использовать && и || в выражениях if, когда нужно несколько пар скобок:
+if [ $NAME == "Steve" ] && [ $AGE -eq 15 ]
+then
+ echo "Исполнится, если $NAME равно Steve И $AGE равно 15."
+fi
+
+if [ $NAME == "Daniya" ] || [ $NAME == "Zach" ]
+then
+ echo "Исполнится, если $NAME равно Daniya ИЛИ Zach."
+fi
+
+# Выражения обозначаются таким форматом:
+echo $(( 10 + 5 ))
+
+# В отличие от других языков программирования, Bash - это командная оболочка,
+# а значит, работает в контексте текущей директории.
+# Вы можете просматривать файлы и директории в текущей директории командой ls:
+ls
+
+# У этой команды есть опции:
+ls -l # Показать каждый файл и директорию на отдельной строке
+
+# Результат предыдущей команды может быть направлен на вход следующей.
+# Команда grep фильтрует ввод по шаблону.
+# Так мы можем просмотреть только *.txt файлы в текущей директории:
+ls -l | grep "\.txt"
+
+# Вы можете перенаправить ввод и вывод команды (stdin, stdout и stderr).
+# Следующая команда означает: читать из stdin, пока не встретится ^EOF$, и
+# перезаписать hello.py следующим строками (до строки "EOF"):
+cat > hello.py << EOF
+#!/usr/bin/env python
+from __future__ import print_function
+import sys
+print("#stdout", file=sys.stdout)
+print("#stderr", file=sys.stderr)
+for line in sys.stdin:
+ print(line, file=sys.stdout)
+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 >> "output.out" 2>> "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)
+echo <(echo "#helloworld")
+
+# Перезаписать output.txt строкой "#helloworld":
+cat > output.out <(echo "#helloworld")
+echo "#helloworld" > output.out
+echo "#helloworld" | cat > output.out
+echo "#helloworld" | tee output.out >/dev/null
+
+# Подчистить временные файлы с подробным выводом ('-i' - интерактивый режим)
+rm -v output.out error.err output-and-error.log
+
+# Команды могут быть подставлены в строку с помощью $( ):
+# следующие команды выводят число файлов и директорий в текущей директории.
+echo "Здесь $(ls | wc -l) элементов."
+
+# То же самое можно сделать с использованием обратных кавычек,
+# но они не могут быть вложенными, поэтому предпочтительно использовать $( ).
+echo "Здесь `ls | wc -l` элементов."
+
+# В Bash есть структура case, которая похожа на switch в Java и C++:
+case "$VARIABLE" in
+ # Перечислите шаблоны для условий, которые хотите отловить
+ 0) echo "Тут ноль.";;
+ 1) echo "Тут один.";;
+ *) echo "Это не пустое значение.";;
+esac
+
+# Цикл for перебирает элементы переданные в аргументе:
+# Содержимое $VARIABLE будет напечатано три раза.
+for VARIABLE in {1..3}
+do
+ echo "$VARIABLE"
+done
+
+# Или с использованием "традиционного" синтаксиса цикла for:
+for ((a=1; a <= 3; a++))
+do
+ echo $a
+done
+
+# Цикл for можно использовать для действий с файлами.
+# Запустим команду 'cat' для файлов file1 и file2
+for VARIABLE in file1 file2
+do
+ cat "$VARIABLE"
+done
+
+# ... или выводом из команд
+# Запустим cat для вывода из ls.
+for OUTPUT in $(ls)
+do
+ cat "$OUTPUT"
+done
+
+# Цикл while:
+while [ true ]
+do
+ echo "тело цикла здесь..."
+ break
+done
+
+# Вы можете определять функции
+# Определение:
+function foo ()
+{
+ echo "Аргументы работают также, как аргументы скрипта: $@"
+ echo "и: $1 $2..."
+ echo "Это функция"
+ return 0
+}
+
+# или просто
+bar ()
+{
+ echo "Другой способ определить функцию!"
+ return 0
+}
+
+# Вызов функции
+foo "Мое имя" $NAME
+
+# Есть много полезных команд, которые нужно знать:
+# напечатать последние 10 строк файла file.txt
+tail -n 10 file.txt
+# напечатать первые 10 строк файла file.txt
+head -n 10 file.txt
+# отсортировать строки file.txt
+sort file.txt
+# отобрать или наоборот пропустить повторяющиеся строки (с опцией -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"
+grep "^foo.*bar$" file.txt
+# передайте опцию -c чтобы вывести число строк, в которых совпал шаблон
+grep -c "^foo.*bar$" file.txt
+# чтобы искать по строке, а не шаблону regex, используйте fgrep (или grep -F)
+fgrep "^foo.*bar$" file.txt
+
+# Читайте встроенную документацию оболочки Bash командой 'help':
+help
+help help
+help for
+help return
+help source
+help .
+
+# Читайте Bash man-документацию
+apropos bash
+man 1 bash
+man bash
+
+# Читайте документацию info (? для помощи)
+apropos info | grep '^info.*('
+man info
+info info
+info 5 info
+
+# Читайте bash info документацию:
+info bash
+info bash 'Bash Features'
+info bash 6
+info --apropos bash
+```
diff --git a/ru-ru/brainfuck-ru.html.markdown b/ru-ru/bf.html.markdown
index 500ac010..d2e74e8f 100644
--- a/ru-ru/brainfuck-ru.html.markdown
+++ b/ru-ru/bf.html.markdown
@@ -1,5 +1,6 @@
---
-language: brainfuck
+language: bf
+filename: learnbf-ru.bf
contributors:
- ["Prajit Ramachandran", "http://prajitr.github.io/"]
- ["Mathias Bynens", "http://mathiasbynens.be/"]
@@ -11,6 +12,8 @@ lang: ru-ru
Brainfuck (пишется маленькими буквами, кроме начала предложения) - это очень
маленький Тьюринг-полный язык программирования лишь с 8 командами.
+Вы можете испытать brainfuck в вашем браузере с помощью [brainfuck-визуализатора](http://fatiherikli.github.io/brainfuck-visualizer/).
+
```
Любой символ, кроме "><+-.,[]", игнорируется, за исключением кавычек.
diff --git a/ru-ru/binary-search-ru.html.markdown b/ru-ru/binary-search-ru.html.markdown
new file mode 100644
index 00000000..9ed62cb8
--- /dev/null
+++ b/ru-ru/binary-search-ru.html.markdown
@@ -0,0 +1,64 @@
+---
+category: Algorithms & Data Structures
+name: Binary Search
+contributors:
+ - ["Abhishek Jaisingh", "http://github.com/abhishekjiitr"]
+translators:
+ - ["Evan K.", "https://github.com/justblah"]
+lang: ru-ru
+---
+
+# Двоичный (бинарный) поиск
+
+## Зачем использовать двоичный поиск?
+
+Поиск является одной из главных проблем в области вычислительной техники. На сегодняшний день осуществляется более одного триллиона поисковых запросов в год, поэтому нам нужны алгоритмы, которые могут делать это очень быстро. Двоичный поиск является одним из фундаментальных алгоритмов в информатике. Для его изучения мы освоим теорию, а затем используем её для реализации алгоритма.
+
+## Вступление
+
+Самый простой вариант поиска – линейный поиск, но этот подход занимает много времени, и растет линейно, пропорционально набору данных. Пример реализации – начинаем с крайнего левого элемента массива S, один за другим сравниваем искомое значение X с каждым элементом массива S, если X совпадает с элементом S, возвращаем индекс. Если X не совпадает ни с одним из элементов массива S, возвращаем -1.
+
+```
+Линейный поиск: O (n) Линейная сложность
+
+Двоичный поиск: O ( log(n) ) Логарифмическая сложность
+
+```
+```
+def search(arr, x):
+
+ for i in range(len(arr)):
+
+ if arr[i] == x:
+ return i
+
+ return -1
+
+```
+
+## Алгоритм двоичного поиска
+
+Для корректной работы двоичного поиска набор данных для поиска должен быть отсортирован (в любом порядке).
+
+### Алгоритм
+
+```
+Главная идея двоичного поиска заключается в использовании информации о том, что массив уже отсортирован,
+что и позволяет упростить сложность алгоритма до O(Logn). Мы попросту отбрасываем половину элементов набора сразу после одного сравнения.
+1) Сравнить X с элементом в середине набора S.
+2) Если X равен элементу в середине - возвращаем индекс среднего элемента.
+3) Если значение X больше, чем средний элемент набора, значит X находится в правой части набора. Повторяем алгоритм для правой половины набора.
+4) В противном случае (X меньше) повторяем алгоритм для левой половины набора.
+Это и есть рекурсивная реализация двоичного поиска.
+
+```
+
+### На заметку
+
+Существует и другая форма двоичного поиска, которая можеть быть полезна.
+
+## На почитать
+
+* [Проектирование, реализация и примеры](https://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA)
+* [Описание алгоритма ИТМО](http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B5%D0%BB%D0%BE%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B4%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA)
+* [Ошибки при реализации бинарного поиска](https://habrahabr.ru/post/146228/)
diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown
new file mode 100644
index 00000000..b9704fc3
--- /dev/null
+++ b/ru-ru/c++-ru.html.markdown
@@ -0,0 +1,892 @@
+---
+language: c++
+filename: learncpp-ru.cpp
+contributors:
+ - ["Steven Basart", "http://github.com/xksteven"]
+ - ["Matt Kline", "https://github.com/mrkline"]
+ - ["Geoff Liu", "http://geoffliu.me"]
+ - ["Connor Waters", "http://github.com/connorwaters"]
+translators:
+ - ["Bohdan Shtepan", "http://modern-dev.com"]
+lang: ru-ru
+---
+
+C++ - компилируемый, статически типизированный язык программирования общего назначения, который,
+[как заявляет создатель языка Бьёрн Страуструп](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote),
+был разработан как
+
+- "лучшая замена C"
+- язык с поддержкой абстракции данных
+- язык с поддержкой объектно-ориентированого программирования
+- язык с поддержкой обобщенного программирования
+
+Хотя его синтаксис может показаться более трудным или сложным для понимания, чем в более современных языках,
+он широко применяется, так как код, написанный на C++, компилируется в набор инструкций, которые могут быть выполнены напрямую
+процессором. C++ широко используется для разработки программного обеспечения, являясь одним из самых популярных языков
+программирования. Область его применения включает создание операционных систем, разнообразных прикладных программ, драйверов
+устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений (игр).
+
+```c++
+//////////////////
+// Сравнение с C
+//////////////////
+
+// C++ практически представляет собой надмножество C и имеет схожий синтаксис
+// для объявления переменных, примитивов и функций.
+
+// Так же, как и в С, точкой входа в программу является функция с именем main,
+// которая возвращает целочисленное значение.
+// Это значение является кодом ответа программы.
+// Смотрите https://goo.gl/JYGKyv для более подробной информации.
+int main(int argc, char** argv)
+{
+ // Аргументы командной строки, переданные в программу, хранятся в переменных
+ // argc и argv, так же, как и в C.
+ // argc указывает на количество аргументов,
+ // а argv является массивом C-подобных строк (char*), который непосредсвенно
+ // содержит аргументы.
+ // Первым аргументом всегда передается имя программы.
+ // argc и argv могут быть опущены, если вы не планируете работать с аругментами
+ // коммандной строки.
+ // Тогда сигнатура функции будет иметь следующий вид: int main()
+
+ // Возвращаемое значение 0 указывает на успешное завершение программы.
+ return 0;
+}
+
+// Тем не менее, C++ имеет свои отличия:
+
+// В C++ символьные литералы имеют тип char.
+sizeof('c') == sizeof(char) == 1
+
+// В C символьные литералы - целые числа.
+sizeof('c') == sizeof(int)
+
+
+// C++ имеет строгое прототипирование.
+void func(); // функция, которая не принимает аргументов.
+
+// В языке C
+void func(); // функция, которая может принять сколько угодно аргументов.
+
+// Использование nullptr вместо NULL в C++.
+int* ip = nullptr;
+
+// Стандартные заголовочные файлы С доступны в С++,
+// но с префиксом "с" и не имеют суффикса .h.
+#include <cstdio>
+
+int main()
+{
+ printf("Hello, world!\n");
+ return 0;
+}
+
+///////////////////////
+// Перегрузка функций
+///////////////////////
+
+// С++ поддерживает перегрузку функций, при условии,
+// что каждая функция принимает различные параметры.
+
+void print(char const* myString)
+{
+ printf("String %s\n", myString);
+}
+
+void print(int myInt)
+{
+ printf("My int is %d", myInt);
+}
+
+int main()
+{
+ print("Hello"); // Использование void print(const char*)
+ print(15); // Использование void print(int)
+}
+
+/////////////////////////////
+// Аргументы функций по умолчанию
+/////////////////////////////
+
+// Вы можете предоставить аргументы по умолчанию для функции,
+// если они не предоставлены при вызове функции.
+
+void doSomethingWithInts(int a = 1, int b = 4)
+{
+ // Здесь что-то делаем с числами
+}
+
+int main()
+{
+ doSomethingWithInts(); // a = 1, b = 4
+ doSomethingWithInts(20); // a = 20, b = 4
+ doSomethingWithInts(20, 5); // a = 20, b = 5
+}
+
+// Аргументы по умолчанию должны быть в конце списка аргументов.
+
+void invalidDeclaration(int a = 1, int b) // Ошибка!
+{
+}
+
+
+/////////////
+// Пространства имен
+/////////////
+
+// Пространства имен предоставляют отдельные области для переменной,
+// функции и других объявлений.
+// Пространства имен могут быть вложенными.
+
+namespace First {
+ namespace Nested {
+ void foo()
+ {
+ printf("This is First::Nested::foo\n");
+ }
+ } // конец пространства имен Nested
+} // конец пространства имен First
+
+namespace Second {
+ void foo()
+ {
+ printf("This is Second::foo\n")
+ }
+}
+
+void foo()
+{
+ printf("This is global foo\n");
+}
+
+int main()
+{
+ // Включает все функци из пространства имен Second в текущую область видимости.
+ // Обратите внимание, что простой вызов foo() больше не работает,
+ // так как теперь не ясно, вызываем ли мы foo из пространства имен Second, или
+ // из глобальной области видимости.
+ using namespace Second;
+
+ Second::foo(); // напечатает "This is Second::foo"
+ First::Nested::foo(); // напечатает "This is First::Nested::foo"
+ ::foo(); // напечатает "This is global foo"
+}
+
+///////////////
+// Ввод и вывод
+///////////////
+
+// Ввод и вывод в C++ использует потоки
+// cin, cout и cerr представляют потоки stdin, stdout и stderr.
+// << - оператор вставки, >> - оператор извлечения.
+
+#include <iostream> // Включение файла для работы с потоками Ввода\Вывода.
+
+using namespace std; // Потоки доступны в пространстве имен std (стандартная библиотека)
+
+int main()
+{
+ int myInt;
+
+ // Выводит в stdout (или в терминал/на экран)
+ cout << "Enter your favorite number:\n";
+ // Принимает ввод
+ cin >> myInt;
+
+ // cout может принимать форматирование
+ cout << "Your favorite number is " << myInt << "\n";
+ // напечатает "Your favorite number is <myInt>"
+
+ cerr << "Used for error messages";
+}
+
+//////////
+// Строки
+//////////
+
+// Строки в C++ являются объектами и имеют много функций-членов.
+#include <string>
+
+using namespace std; // Строки также доступны в пространстве имен std (стандартная библиотека)
+
+string myString = "Hello";
+string myOtherString = " World";
+
+// + используется для конкатенации строк.
+cout << myString + myOtherString; // "Hello World"
+
+cout << myString + " You"; // "Hello You"
+
+// Строки в C++ могут изменяться и имеют семантику значений.
+myString.append(" Dog");
+cout << myString; // "Hello Dog"
+
+
+/////////////
+// Ссылки
+/////////////
+
+// Кроме указателей, доступных в C,
+// C++ имеет _ссылки_.
+// Это такой тип указателя, который не может быть переназначен после инициализации
+// и не может иметь значения null.
+// Ссылки имеют схожий с переменными синтаксис:
+// * больше не используется для разыменования и
+// & (адрес) не используется для назначения.
+
+using namespace std;
+
+string foo = "I am foo";
+string bar = "I am bar";
+
+
+string& fooRef = foo; // Здесь создается ссылка на foo.
+fooRef += ". Hi!"; // Изменяет foo по ссылке
+cout << fooRef; // Печатает "I am foo. Hi!"
+
+// Не переназначает "fooRef". Это то же самое, что и "foo = bar", и
+// foo == "I am bar"
+// после этой строчки.
+cout << &fooRef << endl; // Печатает адрес foo
+fooRef = bar;
+cout << &fooRef << endl; // По-прежнему печатает адрес foo
+cout << fooRef; // Печатает "I am bar"
+
+// Адрес fooRef остается тем же, то есть он по-прежнему ссылается на foo.
+
+
+const string& barRef = bar; // Создает константную ссылку.
+// Так же, как и в C, константные значения (а также указатели и ссылки) не могут быть изменены.
+barRef += ". Hi!"; // Ошибка, константная ссылка не может быть изменена.
+
+// Обходной путь: Прежде чем мы рассмотрим указатели более детально, нам нужно ознакомиться
+// с концепцией, известной как "временный объект". Представьте, что мы имеем следующий код
+string tempObjectFun() { ... }
+string retVal = tempObjectFun();
+
+// Вот что на самом деле происходит во второй строке:
+// - tempObjectFun возвращает строковый объект
+// - из возвращаемого объекта создается новая строка в качестве аргумента конструктору
+// - возвращаемый объект уничтожается
+// Возвращаемый объект называется временным объектом. Временные объекты создаются,
+// когда функция возвращает объект, и уничтожаются в конце выполнения обрамляющего
+// выражения (По крайней мере, так это описывает спецификация, хотя компиляторы могут
+// изменять это поведение. Для более подробной информации смотрите "оптимизация
+// возвращаемого значения".) Таким образом в этом коде:
+foo(bar(tempObjectFun()))
+
+// предполагая, что foo и bar существуют, объект, возвращаемый tempObjectFun, передается
+// в bar, и уничтожается перед вызовом foo.
+
+// Возвращаемся к указателям. Исключением для правила "в конце выполнения обрамляющего
+// выражения" является временный объект, привязанный к ссылке const, в этом случае
+// его жизненный цикл продлевается до текущей области видимости:
+
+void constReferenceTempObjectFun() {
+ // constRef получает временный объект, и он действителен до конца этой функции.
+ const string& constRef = tempObjectFun();
+ ...
+}
+
+// В C++11 предоставлен еще один тип ссылок специально для временных объектов.
+// objects. Вы не можете объявить переменную этого типа, но он имеет приоритет
+// в резолюции перегрузки:
+
+void someFun(string& s) { ... } // Обычная ссылка
+void someFun(string&& s) { ... } // Ссылка на временный объект
+
+string foo;
+someFun(foo); // Выполняет версию с обычной ссылкой
+someFun(tempObjectFun()); // Выполняет версию с временной ссылкой.
+
+// Например, существуют следующие две версии конструктора std::basic_string:
+basic_string(const basic_string& other);
+basic_string(basic_string&& other);
+
+// Идея в том, что если мы конструируем новую строку из временного объекта (который
+// так или иначе будет уничтожен), мы можем использовать более эффективный конструктор,
+// который "спасает" части этой временной строки. Эта концепция была названа
+// "move semantics".
+
+/////////////////////
+// Перечисления
+/////////////////////
+
+// Перечисления - способ объявления констант и установки их значений, в основном
+// использующийся для упрощения чтения кода.
+enum ECarTypes
+{
+ Sedan,
+ Hatchback,
+ SUV,
+ Wagon
+};
+
+ECarTypes GetPreferredCarType()
+{
+ return ECarTypes::Hatchback;
+}
+
+// На момент выхода C++11 есть простой способ назначения типа перечисления, что
+// полезно в случае сериализации данных и преобразований между конечным типом и
+// соответствующими константами.
+enum ECarTypes : uint8_t
+{
+ Sedan, // 0
+ Hatchback, // 1
+ SUV = 254, // 254
+ Hybrid // 255
+};
+
+void WriteByteToFile(uint8_t InputValue)
+{
+ // Сериализуем InputValue в файл
+}
+
+void WritePreferredCarTypeToFile(ECarTypes InputCarType)
+{
+ // Перечисление неявно преобразуется в uint8_t из-за ранее объявленного
+ // типа перечисления.
+ WriteByteToFile(InputCarType);
+}
+
+// С другой стороны, чтобы избежать случайного приведения к целочисленному типу или
+// другому перечислению, вы можете создать класс перечисления, который не будет
+// преобразовываться неявно.
+enum class ECarTypes : uint8_t
+{
+ Sedan, // 0
+ Hatchback, // 1
+ SUV = 254, // 254
+ Hybrid // 255
+};
+
+void WriteByteToFile(uint8_t InputValue)
+{
+ // Сериализуем InputValue в файл
+}
+
+void WritePreferredCarTypeToFile(ECarTypes InputCarType)
+{
+ // Хотя ECarTypes имеет тип uint8_t, код не будет скомпилирован из-за того,
+ // что перечисление было объявлено как класс перечисления.
+ WriteByteToFile(InputCarType);
+}
+
+//////////////////////////////////////////
+// Классы и объектно-ориентированное программирование
+//////////////////////////////////////////
+
+// Пример классов
+#include <iostream>
+
+// Объявление класса.
+// Обычно классы объявляют в заголовочном (.h или .hpp) файле.
+class Dog {
+ // Переменные-члены и функции являются приватными по умолчанию.
+ std::string name;
+ int weight;
+
+// Все члены после этой сроки являются открытыми
+// пока "private:" или "protected:" не будет объявлено.
+public:
+
+ // Конструктор по умолчанию
+ Dog();
+
+ // Объявление функций-членов
+ // Обратите внимание, мы используем std::string здесь вместо использования
+ // using namespace std;
+ // выше.
+ // Никогда не размещайте выражение "using namespace" в заголовке.
+ void setName(const std::string& dogsName);
+
+ void setWeight(int dogsWeight);
+
+ // Функции, которые не изменяют состояние объекта,
+ // должны быть помечены как const.
+ // Это позволяет вызывать их, если дана const ссылка на объект.
+ // Обратите внимание, функции должны быть явно объявлены как _virtual_,
+ // если вы хотите перегрузить их в производных классах.
+ // Функции не являются виртуальными по умолчанию для повышения производительности.
+ virtual void print() const;
+
+ // Также функции могут быть определены внутри тела класса.
+ // Функции, определенные следующим образом, автоматически встроены.
+ void bark() const { std::cout << name << " barks!\n"; }
+
+ // Наряду с конструкторами, в C++ есть деструкторы.
+ // Они вызываются, когда объект удаляется или выпадает из области видимости.
+ // Это активирует мощную парадигму программирования, известную как RAII
+ // (смотрите ниже)
+ // Деструктор должен быть виртуальным, если класс будет производным.
+ // Если он не виртуальный, тогда деструктор производного класса не будет вызван,
+ // если объект удален по ссылке или указателю базового класса.
+ virtual ~Dog();
+
+}; // Определение класса должно завершаться точкой с запятой.
+
+// Функции-члены класса, как правило, реализуются в .cpp файлах.
+Dog::Dog()
+{
+ std::cout << "A dog has been constructed\n";
+}
+
+// Объекты (такие как строки) должны передаваться по ссылке если вы будете
+// изменять их, или const-ссылке если нет.
+void Dog::setName(const std::string& dogsName)
+{
+ name = dogsName;
+}
+
+void Dog::setWeight(int dogsWeight)
+{
+ weight = dogsWeight;
+}
+
+// Обратите внимание, "virtual" требуется только в объявлении, не в определении.
+void Dog::print() const
+{
+ std::cout << "Dog is " << name << " and weighs " << weight << "kg\n";
+}
+
+Dog::~Dog()
+{
+ std::cout << "Goodbye " << name << "\n";
+}
+
+int main() {
+ Dog myDog; // Печатает "A dog has been constructed"
+ myDog.setName("Barkley");
+ myDog.setWeight(10);
+ myDog.print(); // Печатает "Dog is Barkley and weighs 10 kg"
+ return 0;
+} // Печатает "Goodbye Barkley"
+
+// Интерфейсы:
+
+// Этот класс наследует все открытые и защищенные члены класса Dog
+// так же, как и все закрытые, но не может непосредственно получить доступ к закрытым
+// членам\методам без открытых или защищенных методов для этого.
+class OwnedDog : public Dog {
+
+ void setOwner(const std::string& dogsOwner);
+
+ // Переопределяем поведение функции печати для всех OwnedDog. Смотрите
+ // https://goo.gl/3kuH2x для боле общего введения, если вы не знакомы
+ // с концепцией полиморфизма подтипов (включения).
+ // Ключевое слово override является необязательным, но указывает, что метод
+ // на самом деле перегружается в базовом классе.
+ void print() const override;
+
+private:
+ std::string owner;
+};
+
+// Тем временем, в соответствующем .cpp файле:
+
+void OwnedDog::setOwner(const std::string& dogsOwner)
+{
+ owner = dogsOwner;
+}
+
+void OwnedDog::print() const
+{
+ Dog::print(); // Вызывает функцию print в базовом классе Dog
+ std::cout << "Dog is owned by " << owner << "\n";
+ // Печатает "Dog is <name> and weights <weight>"
+ // "Dog is owned by <owner>"
+}
+
+//////////////////////////////////////////
+// Инициализация и перегрузка операторов.
+//////////////////////////////////////////
+
+// В C++ вы можете перегрузить поведение таких операторов: +, -, *, / и др..
+// Это делается путем определения функции, которая вызывается,
+// когда используется оператор.
+
+#include <iostream>
+using namespace std;
+
+class Point {
+public:
+ // Значения по умолчанию для переменных-членов могут быть установлены
+ // следующим образом.
+ double x = 0;
+ double y = 0;
+
+ // Определяем новый конструктор, который инициализирует Point со значениями
+ // по умолчанию (0, 0)
+ Point() { };
+
+ // Следующий синтаксис известен как список инициализации и является верным способом
+ // инициализировать значения членов класса.
+ Point (double a, double b) :
+ x(a),
+ y(b)
+ { /* Ничего не делайте, кроме инициализации значений */ }
+
+ // Перегружаем оператор +.
+ Point operator+(const Point& rhs) const;
+
+ // Перегружаем оператор +=.
+ Point& operator+=(const Point& rhs);
+
+ // Имеет смысл добавить перегрузку операторов - и -=,
+ // но для краткости мы опустим эти детали.
+};
+
+Point Point::operator+(const Point& rhs) const
+{
+ // Создает новую точку, которая является суммой этой точки и rhs.
+ return Point(x + rhs.x, y + rhs.y);
+}
+
+Point& Point::operator+=(const Point& rhs)
+{
+ x += rhs.x;
+ y += rhs.y;
+ return *this;
+}
+
+int main () {
+ Point up (0,1);
+ Point right (1,0);
+ // Здесь происходит вызов оператора + класса Point
+ // Точка "up" вызывает + (функция) с параметром "right"
+ Point result = up + right;
+ // Печатает "Result is upright (1,1)"
+ cout << "Result is upright (" << result.x << ',' << result.y << ")\n";
+ return 0;
+}
+
+/////////////////////
+// Шаблоны
+/////////////////////
+
+// Шаблоны в С++, в основном, используются для обобщенного программирования, хотя
+// они гораздо более мощны, чем дженерики в других языках. Они также поддерживают
+// явные, частные и функциональные типы классов; на самом деле, они являются
+// тьюринг-полным языком, встроенным в C++!
+
+// Мы начнем с наиболее распространенного типа обобщенного программирования. Чтобы
+// определить класс или функцию, которая принимает параметр типа:
+template<class T>
+class Box {
+public:
+ // В этом классе T может быть любого типа.
+ void insert(const T&) { ... }
+};
+
+// Во время компиляции компилятор фактически генерирует копии каждого шаблона
+// с замещенными параметрами, поэтому полное определение класса должно присутствовать
+// при каждом вызове. Именно поэтому классы шаблонов полностью определены в
+// заголовочных файлах.
+
+// Чтобы создать экземпляр класса шаблона на стеке:
+Box<int> intBox;
+
+// и вы можете использовать его, как и ожидалось:
+intBox.insert(123);
+
+// Вы, конечно, можете использовать вложенные шаблоны:
+Box<Box<int> > boxOfBox;
+boxOfBox.insert(intBox);
+
+// Вплоть до С++11, вы должны были ставить пробел между двумя символами '>', иначе '>>'
+// принимался парсером, как оператор сдвига вправо.
+
+// Иногда вы можете увидеть
+// template<typename T>
+// вместо этого. В этом случае ключевые слова 'class' и 'typename' _в основном_
+// взаимозаменяемыми. Для более подробной информации смотрите
+// http://en.wikipedia.org/wiki/Typename
+// (да-да, это ключевое слово имеет собственную страничку на вики).
+
+// Аналогичным образом, шаблонная функция:
+template<class T>
+void barkThreeTimes(const T& input)
+{
+ input.bark();
+ input.bark();
+ input.bark();
+}
+
+// Обратите внимание, что здесь ничего не указано о типе параметра. Компилятор
+// будет генерировать и затем проверять на тип каждый вызов шаблона, поэтому
+// данная функция работает с любым типом 'T', который имеет метод 'bark'.
+
+Dog fluffy;
+fluffy.setName("Fluffy");
+barkThreeTimes(fluffy); // Печатает "Fluffy barks" три раза.
+
+//Параметры шаблона не должны быть классами:
+template<int Y>
+void printMessage() {
+ cout << "Learn C++ in " << Y << " minutes!" << endl;
+}
+
+// В конце концов, вы можете явно специализировать шаблоны для более эффективного
+// кода. Конечно, большинство реальных случаев использования специализации
+// не так тривиально, как это. Обратите внимание, вам все еще нужно явно объявить
+// функцию (или класс) в качестве шаблона, даже если вы явно указали все параметры.
+template<>
+void printMessage<10>() {
+ cout << "Learn C++ faster in only 10 minutes!" << endl;
+}
+
+printMessage<20>(); // Печатает "Learn C++ in 20 minutes!"
+printMessage<10>(); // Печатает "Learn C++ faster in only 10 minutes!"
+
+
+/////////////////////
+// Обработка исключений
+/////////////////////
+
+// Стандартная библиотека предоставляет несколько типов исключений
+// (смотрите http://en.cppreference.com/w/cpp/error/exception)
+// но, в принципе, любой тип может быть брошен в качестве исключения.
+#include <exception>
+#include <stdexcept>
+
+// Все исключения, брошенные в блоке _try_ могут быть пойманы в последующем блоке
+// _catch_.
+try {
+ // Не выделяйте память в куче для исключений с помощью ключевого слова _new_.
+ throw std::runtime_error("A problem occurred");
+}
+
+// Поймайте исключение по константной ссылке, если оно является объектом
+catch (const std::exception& ex)
+{
+ std::cout << ex.what();
+}
+
+// Ловит любое исключение, не пойманное предыдущим блоком _catch_
+catch (...)
+{
+ std::cout << "Unknown exception caught";
+ throw; // Повторный выброс исключения
+}
+
+///////
+// Получение ресурса есть инициализация (RAII)
+///////
+
+// Программная идиома объектно-ориентированного программирования, смысл которой
+// заключается в том, что с помощью тех или иных программных механизмов получение
+// некоторого ресурса неразрывно совмещается с инициализацией, а освобождение -
+// с уничтожением объекта.
+
+// Чтобы понять, на сколько это полезно,
+// рассмотрим функцию, которая использует обработчик файлов в С:
+void doSomethingWithAFile(const char* filename)
+{
+ // Для начала, предположим, ничего не может потерпеть неудачу.
+
+ FILE* fh = fopen(filename, "r"); // Открываем файл в режиме чтения.
+
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+
+ fclose(fh); // Закрываем обработчик файла.
+}
+
+// К сожалению, вещи быстро осложняются обработкой ошибок.
+// Предположим, fopen может потерпеть неудачу, тогда doSomethingWithTheFile и
+// doSomethingElseWithIt вернут коды ошибок, если потерпят неудачу.
+// (Исключения являются предпочтительным способом обработки ошибок,
+// но некоторые программисты, особенно те, кто имеет большой опыт работы с С,
+// не согласны с аргументами о полезности исключений).
+// Теперь мы должны проверить каждый вызов на наличие ошибок и закрыть обработчик
+// файла, если он есть.
+bool doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r"); // Открывает файл в режиме чтения
+ if (fh == nullptr) // В случае неудачи возвращаемый указатель принимает значение null.
+ return false; // Сообщает о неудаче вызывающему.
+
+ // Предположим, каждая функция возвращает false в случае неудачи
+ if (!doSomethingWithTheFile(fh)) {
+ fclose(fh); // Закрываем обработчик файла, чтобы не было утечек
+ return false; // Сообщает об ошибке.
+ }
+ if (!doSomethingElseWithIt(fh)) {
+ fclose(fh); // Закрываем обработчик файла, чтобы не было утечек
+ return false; // Сообщает об ошибке.
+ }
+
+ fclose(fh); // Закрываем обработчик файла, чтобы не было утечек
+ return true; // Указывает на успех
+}
+
+// C-программисты часто упорядочивают это с помощью goto:
+bool doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r");
+ if (fh == nullptr)
+ return false;
+
+ if (!doSomethingWithTheFile(fh))
+ goto failure;
+
+ if (!doSomethingElseWithIt(fh))
+ goto failure;
+
+ fclose(fh); // Закрываем файл.
+ return true; // Указывает на успех
+
+failure:
+ fclose(fh);
+ return false; // Сообщает об ошибке.
+}
+
+// Если функции указывают на ошибки с помощью исключений, вещи становятся проще,
+// но все еще не оптимальны.
+void doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r"); // Открываем файл в режиме чтения
+ if (fh == nullptr)
+ throw std::runtime_error("Could not open the file.");
+
+ try {
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+ }
+ catch (...) {
+ fclose(fh); // Убедитесь, что закрываете файл, если происходит ошибка.
+ throw; // Затем повторно бросает исключение.
+ }
+
+ fclose(fh); // Закрываем файл.
+ // Успех
+}
+
+// Сравните это с использованием класса потока файла (fstream) в С++, который
+// использует свой деструктор, чтобы закрыть файл. Еще раз взгляните выше,
+// деструктор вызывается автоматически, когда объект выпадает из области видимости.
+void doSomethingWithAFile(const std::string& filename)
+{
+ // ifstream определяет файловый поток
+ std::ifstream fh(filename); // Открыть файл
+
+ // Что-то делать с файлом
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+
+} // Здесь файл автоматически закрывается в деструкторе.
+
+// Это имеет _огромнейшие_ преимущества:
+// 1. Неважно, что произойдет,
+// ресурсы (в данном случае дескриптор файла) будут очищены.
+// После того, как вы правильно напишете деструктор,
+// Больше будет _невозможно_ закрыть обработчик файлов или допустить утечку.
+// 2. Обратите внимание, что код намного проще.
+// Деструктор закрывает файловый поток "за кулисами", и вам больше не нужно об
+// этом беспокоиться.
+// 3. Код устойчив к исключениям.
+// Исключение может быть брошено в любом месте в функции, и это никак не повлияет
+// на очистку.
+
+// Весь идиоматический код на С++ широко использует RAII для всех ресурсов.
+// Дополнительные примеры включат:
+// - Использование памяти unique_ptr и shared_ptr
+// - Контейнеры - стандартная библиотека связанных списков, векторы
+// (т.е. самоизменяемые массивы), хэш-таблицы и все остальное автоматически
+// уничтожается сразу же, когда выходит за пределы области видимости.
+// - Ипользование мьютексов lock_guard и unique_lock
+
+// Контейнеры с пользовательскими классами в качестве ключей требуют
+// сравнивающих функций в самом объекте или как указатель на функцию. Примитивы
+// имеют компараторы по умолчанию, но вы можете перегрузить их.
+class Foo {
+public:
+ int j;
+ Foo(int a) : j(a) {}
+};
+struct compareFunction {
+ bool operator()(const Foo& a, const Foo& b) const {
+ return a.j < b.j;
+ }
+};
+// это не допускается (хотя это может варьироваться в зависимости от компилятора)
+// std::map<Foo, int> fooMap;
+std::map<Foo, int, compareFunction> fooMap;
+fooMap[Foo(1)] = 1;
+fooMap.find(Foo(1)); //true
+
+/////////////////////
+// Веселые вещи
+/////////////////////
+
+// Аспекты С++, которые могут быть удивительными для новичков (и даже для некоторых
+// ветеранов). Этот раздел, к сожалению, очень неполон. С++ является одним из самых
+// простых языков, где очень легко выстрелить себе в ногу.
+
+// Вы можете перегрузить приватные методы!
+class Foo {
+ virtual void bar();
+};
+class FooSub : public Foo {
+ virtual void bar(); // Перегружает Foo::bar!
+};
+
+
+// 0 == false == NULL (в основном)!
+bool* pt = new bool;
+*pt = 0; // Устанавливает значение указателя 'pt' в false.
+pt = 0; // Устанавливает значение 'pt' в нулевой указатель. Обе строки проходят
+ // компиляцию без ошибок.
+
+// nullptr приходит на помощь:
+int* pt2 = new int;
+*pt2 = nullptr; // Не пройдет компиляцию
+pt2 = nullptr; // Устанавливает pt2 в null.
+
+// Существует исключение для булевых значений.
+// Это позволит вам проверить указатели с помощью if(!ptr),
+// но как следствие вы можете установить nullptr в bool напрямую!
+*pt = nullptr; // Это по прежнему проходит компиляцию, даже если '*pt' - bool!
+
+
+// '=' != '=' != '='!
+// Вызывает Foo::Foo(const Foo&) или некий вариант (смотрите "move semantics")
+// конструктора копирования.
+Foo f2;
+Foo f1 = f2;
+
+// Вызывает Foo::Foo(const Foo&) или вариант, но копирует только часть 'Foo' из
+// 'fooSub'. Любые другие члены 'fooSub' пропускаются. Иногда это ужасное поведение
+// называют "object slicing."
+FooSub fooSub;
+Foo f1 = fooSub;
+
+// Вызывает Foo::operator=(Foo&) или вариант.
+Foo f1;
+f1 = f2;
+
+
+// Как по-настоящему очистить контейнер:
+class Foo { ... };
+vector<Foo> v;
+for (int i = 0; i < 10; ++i)
+ v.push_back(Foo());
+
+// В следующей точке размер v устанавливается в 0, но деструктор не вызывается
+// и не происходит очистка ресурсов!
+v.empty();
+v.push_back(Foo()); // Новые значения копируются в первый вставленный Foo
+
+// Настоящее уничтожение всех значений v. Смотрите раздел о временном объекте
+// для объяснения того, как это работает.
+v.swap(vector<Foo>());
+
+```
+## Дальнейшее чтение:
+
+Наиболее полное и обновленное руководство по С++ можно найти на
+<http://cppreference.com/w/cpp>
+
+Дополнительные ресурсы могут быть найдены на <http://cplusplus.com>
diff --git a/ru-ru/c-ru.html.markdown b/ru-ru/c-ru.html.markdown
index 5988b159..44e7ad3b 100644
--- a/ru-ru/c-ru.html.markdown
+++ b/ru-ru/c-ru.html.markdown
@@ -11,7 +11,7 @@ lang: ru-ru
Что ж, Си всё ещё является лидером среди современных высокопроизводительных языков.
-Для большинствоа программистов, Си – это самый низкоуровневый язык на котором они когда-либо писали,
+Для большинства программистов, Си – это самый низкоуровневый язык на котором они когда-либо писали,
но этот язык даёт больше, чем просто повышение производительности.
Держите это руководство в памяти и вы сможете использовать Си максимально эффективно.
@@ -145,7 +145,7 @@ int main() {
f1 / f2; // => 0.5, плюс-минус погрешность потому что,
// цифры с плавающей точкой вычисляются неточно!
- // Модуль
+ // Остаток от деления
11 % 3; // => 2
// Операции сравнения вам уже знакомы, но в Си нет булевого типа.
@@ -170,7 +170,7 @@ int main() {
!0; // => 1
1 && 1; // => 1 (логическое И)
0 && 1; // => 0
- 0 || 1; // => 1 (лигическое ИЛИ)
+ 0 || 1; // => 1 (логическое ИЛИ)
0 || 0; // => 0
// Битовые операторы
@@ -202,7 +202,7 @@ int main() {
int ii = 0;
while (ii < 10) {
printf("%d, ", ii++); // инкрементация происходит после того как
- // знаечние ii передано ("postincrement")
+ // значение ii передано ("postincrement")
} // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
@@ -212,7 +212,7 @@ int main() {
do {
printf("%d, ", kk);
} while (++kk < 10); // инкрементация происходит перед тем как
- // передаётся знаечние kk ("preincrement")
+ // передаётся значение kk ("preincrement")
// => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
@@ -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
@@ -285,17 +285,17 @@ int main() {
printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer));
// => Напечатает "8, 4" в 64 битной системе
- // Для того, чтобы получить знаечние по адресу, напечатайте * перед именем.
- // Да, использование * при объявлении указателя и получении значения по адресу
+ // Для того, чтобы получить значение по адресу, напечатайте * перед именем.
+ // Да, * используется при объявлении указателя и для получении значения по адресу
// немного запутано, но вы привыкнете.
- 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++) {
@@ -305,9 +305,10 @@ int main() {
// Объявление указателя на int с адресом массива.
int* x_ptr = x_array;
// x_ptr сейчас указывает на первый элемент массива (со значением 20).
- // Это рабоатет, потому что имя массива возвращает указатель на первый элемент.
- // Например, когда массив передаётся в функцию или назначается указателю, он
- // невявно преобразуется в указатель.
+ // Это работает, потому что при обращении к имени массива возвращается
+ // указатель на первый элемент.
+ // Например, когда массив передаётся в функцию или присваивается указателю, он
+ // неяввно преобразуется в указатель.
// Исключения: когда массив является аргументом для оператор '&':
int arr[10];
int (*ptr_to_arr)[10] = &arr; // &arr не является 'int *'!
@@ -422,7 +423,7 @@ void function_1() {
// Вы можете объявить указатель на структуру
struct rectangle *my_rec_ptr = &my_rec;
- // Можно доступаться к структуре и через указатель
+ // Можно получить доступ к структуре и через указатель
(*my_rec_ptr).width = 30;
// ... или ещё лучше: используйте оператор -> для лучшей читабельночти
@@ -436,7 +437,7 @@ int area(rect r) {
return r.width * r.height;
}
-// Если вы имеете большую структуру, можно доступаться к ней "по указателю",
+// Если вы имеете большую структуру, можно получить доступ к ней "по указателю",
// чтобы избежать копирования всей структуры.
int area(const rect *r) {
return r->width * r->height;
@@ -456,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;" тоже будет работать.
//Имя функции (как и массива) возвращает указатель на начало.
@@ -476,7 +477,7 @@ void str_reverse_through_pointer(char *str_in) {
Очень важно использовать правильные отступы и ставить пробелы в нужных местах.
Читаемый код лучше чем красивый или быстрый код.
-Чтобы научиться писать хороший код, почитайте [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 2f508a00..356d1cc0 100644
--- a/ru-ru/clojure-ru.html.markdown
+++ b/ru-ru/clojure-ru.html.markdown
@@ -144,7 +144,7 @@ Clojure, это представитель семейства Lisp-подобн
;;;;;;;;;;;;;;;;;;;;;
; Функция создается специальной формой fn.
-; "Тело"" функции может состоять из нескольких форм,
+; "Тело" функции может состоять из нескольких форм,
; но результатом вызова функции всегда будет результат вычисления
; последней из них.
(fn [] "Hello World") ; => fn
@@ -321,7 +321,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут
; Также модуль может быть импортирован формой require
(require 'clojure.string)
-; После этого модуль становится доступе в текущем пространстве имен,
+; После этого модуль становится доступен в текущем пространстве имен,
; а вызов его функций может быть осуществлен указанием полного имени функции:
(clojure.string/blank? "") ; => true
diff --git a/ru-ru/css-ru.html.markdown b/ru-ru/css-ru.html.markdown
new file mode 100644
index 00000000..e0e5e30b
--- /dev/null
+++ b/ru-ru/css-ru.html.markdown
@@ -0,0 +1,250 @@
+---
+language: css
+contributors:
+ - ["Mohammad Valipour", "https://github.com/mvalipour"]
+ - ["Marco Scannadinari", "https://github.com/marcoms"]
+ - ["Geoffrey Liu", "https://github.com/g-liu"]
+filename: learncss-ru.css
+lang: ru-ru
+---
+
+В свои ранние дни веб состоял в основном из чистого текста. С развитием браузеров
+веб-страницы с графическими элементами стали обычным делом.
+CSS - язык, разграничивающий содержимое (HTML) и внешний вид веб-страниц.
+
+Если коротко, то CSS предоставляет синтаксис, позволяющий выбирать различные
+HTML элементы и определять их внешний вид.
+
+Как и у других языков, у CSS много версий. Мы описываем CSS2.0 - не самую новую,
+но самую поддерживаемую и распространенную версию.
+
+**ВАЖНО:** Так как результатом применения CSS является изменение внешнего вида
+элементов, постарайтесь использовать CSS-песочницы при изучении языка.
+Например [dabblet](http://dabblet.com/).
+В данной статье рассматриваются в первую очередь синтаксис и общие рекомендации.
+
+
+```css
+/* Для комментариев используется слеш-астериск, как на этой строчке.
+ В CSS нет однострочных комментариев; все комментарии записываются таким способом */
+
+/* ####################
+ ## СЕЛЕКТОРЫ
+ #################### */
+
+/* Выражения в CSS очень просты */
+селектор { атрибут: значение; /* другие атрибуты...*/ }
+
+/* селекторы используются для выбора элементов на странице
+
+Чтобы выбрать все элементы, используйте астериск: */
+* { color:red; }
+
+/*
+Если на странице присутствует такой элемент:
+
+<div class='some-class class2' id='someId' attr='value' otherAttr='en-us foo bar' />
+*/
+
+/* его можно выбрать по одному классу */
+.some-class { }
+
+/* или по обоим классам */
+.some-class.class2 { }
+
+/* по названию тега */
+div { }
+
+/* по идентификатору */
+#someId { }
+
+/* по имеющемуся атрибуту */
+[attr] { font-size:smaller; }
+
+/* или по атрибуту с определенным значением */
+[attr='value'] { font-size:smaller; }
+
+/* можно выбрать атрибуты, начинающиеся с определенного значения (CSS3) */
+[attr^='val'] { font-size:smaller; }
+
+/* или заканчивающиеся определенным значением (CSS3) */
+[attr$='ue'] { font-size:smaller; }
+
+/* содержащие отделенное пробелами значение в названии атрибута (CSS3) */
+[otherAttr~='foo'] { font-size:smaller; }
+
+/* можно выбрать атрибут как с точным, так и со стоящим после значения “-” (U+002D) */
+[otherAttr|='en'] { font-size:smaller; }
+
+
+/* Более того, все это можно использовать вместе - между разными частями
+не должно быть пробелов, иначе селектор будет иметь совершенно иное значение */
+div.some-class[attr$='ue'] { }
+
+/* Вы можете выбрать элемент по его родителю */
+
+/* прямой потомок другого элемента (выбранного с помощью селектора) */
+div.some-parent > .class-name {}
+
+/* потомок любого родителя в дереве элементов
+ следующая строка означает: "любой элемент класса "class-name",
+ являющийся потомком div-элемента класса "some-parent"
+ НЕЗАВИСИМО ОТ УРОВНЯ ВЛОЖЕННОСТИ" */
+div.some-parent .class-name {}
+
+/* важно: этот же селектор без пробелов имеет иное значение
+ можете догадаться, какое? */
+div.some-parent.class-name {}
+
+/* вы можете выбрать элемент по первому предшествующему
+ родственному элементу */
+.i-am-before + .this-element { }
+
+/* или любому предшествующему родственнику перед элементом */
+.i-am-any-before ~ .this-element {}
+
+
+/* Существуют псевдо-классы, позволяющие изменять внешний вид элемента
+ в зависимости от событий, произошедших с элементом */
+
+/* например, когда курсор наведен на элемент */
+element:hover {}
+
+/* когда пользователь проходил по ссылке ранее */
+element:visited {}
+
+/* или еще не проходил по ней */
+element:link {}
+
+/* выбранное поле ввода (input) */
+element:focus {}
+
+
+/* ####################
+ ## АТРИБУТЫ
+ #################### */
+
+selector {
+
+ /* Единицы измерения */
+ width: 50%; /* проценты */
+ font-size: 2em; /* умножается на высоту шрифта (2em - в два раза больше) */
+ width: 200px; /* пиксели */
+ font-size: 20pt; /* пункты */
+ width: 5cm; /* сантиметры */
+ min-width: 50mm; /* миллиметры */
+ max-width: 5in; /* дюймы */
+ height: 0.2vh; /* умножается на высоту окна браузера (CSS3) */
+ width: 0.4vw; /* умножается на ширину окна браузера (CSS3) */
+ min-height: 0.1vmin; /* наименьшее из vh и vw (CSS3) */
+ max-width: 0.3vmax; /* наибольшее из vh и vw (CSS3) */
+
+ /* Цвета */
+ background-color: #F6E; /* сокращенная запись шестнадцатеричного кода */
+ background-color: #F262E2; /* стандартная запись шестнадцатеричного кода */
+ background-color: tomato; /* название цвета */
+ background-color: rgb(255, 255, 255); /* цветовая модель rgb */
+ background-color: rgb(10%, 20%, 50%); /* цветовая модель rgb в процентах */
+ background-color: rgba(255, 0, 0, 0.3); /* цветовая модель rgb (последний аргумент отвечает за прозрачность цвета) (CSS3) */
+ background-color: transparent; /* прозрачный цвет */
+ background-color: hsl(0, 100%, 50%); /* в формате hsl (CSS3) */
+ background-color: hsla(0, 100%, 50%, 0.3); /* в формате hsl (последний аргумент отвечает за непрозрачность цвета) (CSS3) */
+
+
+ /* Изображения */
+ background-image: url(/path-to-image/image.jpg); /* кавычки внутри url() опциональны */
+
+ /* Шрифты */
+ font-family: Arial;
+ font-family: "Courier New"; /* если в названии есть пробелы, заключите его в кавычки */
+ font-family: "Courier New", Trebuchet, Arial, sans-serif; /* если шрифт не найден,
+ будет использован следующий за ним в списке */
+}
+
+```
+
+## Использование
+
+Сохраните готовый файл с расширением .css
+
+```xml
+<!-- добавьте css файл в тег <head> на странице: -->
+<link rel='stylesheet' type='text/css' href='path/to/style.css' />
+
+<!-- Можно использовать встроенные стили. Рекомендуется избегать подобного подхода. -->
+<body>
+ <style>
+ a { color: purple; }
+ </style>
+</body>
+
+<!-- Можно установить стиль элемента напрямую.
+Используйте этот способ только в случае крайней необходимости. -->
+<div style="border: 1px solid red;">
+</div>
+
+```
+
+## Приоритет
+
+Как вы заметили, внешний вид элемента может определяться несколькими селекторами,
+а значение атрибута элемента может быть установлено больше одного раза.
+В подобных случаях одно из значений оказывается приоритетнее остальных.
+
+Если взять следующую таблицу стилей:
+
+```css
+/*A*/
+p.class1[attr='value']
+
+/*B*/
+p.class1 {}
+
+/*C*/
+p.class2 {}
+
+/*D*/
+p {}
+
+/*E*/
+p { property: value !important; }
+
+```
+
+и следующую разметку:
+
+```xml
+<p style='/*F*/ property:value;' class='class1 class2' attr='value'>
+</p>
+```
+
+Приоритет стилей будет таким:
+Помните: приоритет выставляется для **атрибута**, а не для всего блока стилей.
+
+* `E` имеет наивысший приоритет благодаря ключевому слову `!important`.
+ Используйте только в случае крайней необходимости.
+* `F` идет следующим, так как является встроенным стилем.
+* `A` следующий, как самый конкретизированный.
+ конкретизированный == большее количество определителей.
+ В этом примере 3 определителя: 1 тег `p` +
+ название класса `class1` + 1 атрибут `attr='value'`
+* `C` следующий. Несмотря на одинаковое с `B` количество определителей,
+ `C` определен позже.
+* Затем `B`
+* И последний `D`.
+
+## Совместимость
+
+Несмотря на то, что большая часть функций CSS2 (а также CSS3) поддерживается всеми
+браузерами и устройствами, не забывайте проверять совместимость CSS-правил
+с современными браузерами.
+
+[QuirksMode CSS](http://www.quirksmode.org/css/) замечательно подходит для этого.
+
+To run a quick compatibility check, [CanIUse](http://caniuse.com) is a great resource.
+
+## Ресурсы для самостоятельного изучения
+
+* [Understanding Style Precedence in CSS: Specificity, Inheritance, and the Cascade](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/)
+* [QuirksMode CSS](http://www.quirksmode.org/css/)
+* [Z-Index - The stacking context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context)
diff --git a/ru-ru/d-ru.html.markdown b/ru-ru/d-ru.html.markdown
new file mode 100644
index 00000000..bfa3f085
--- /dev/null
+++ b/ru-ru/d-ru.html.markdown
@@ -0,0 +1,754 @@
+---
+language: D
+filename: learnd-ru.d
+contributors:
+ - ["Anton Pastukhov", "http://dprogramming.ru/"]
+ - ["Robert Brights-Gray", "http://lhs-blog.info/"]
+ - ["Andre Polykanine", "http://oire.me/"]
+lang: ru-ru
+---
+
+D - современный компилируемый язык общего назначения с Си-подобным синтаксисом,
+который сочетает удобство, продуманный дизайн и высокую производительность.
+D - это С++, сделанный правильно.
+
+```c
+// Welcome to D! Это однострочный комментарий
+
+/* многострочный
+ комментарий */
+
+/+
+ // вложенные комментарии
+
+ /* еще вложенные
+ комментарии */
+
+ /+
+ // мало уровней вложенности? Их может быть сколько угодно.
+ +/
++/
+
+/*
+ Имя модуля. Каждый файл с исходным кодом на D — модуль.
+ Если имя не указано явно, то предполагается, что оно совпадает с именем
+ файла. Например, для файла "test.d" имя модуля будет "test", если явно
+ не указать другое
+ */
+module app;
+
+// импорт модуля. Std — пространство имен стандартной библиотеки (Phobos)
+import std.stdio;
+
+// можно импортировать только нужные части, не обязательно модуль целиком
+import std.exception : enforce;
+
+// точка входа в программу — функция main, аналогично C/C++
+void main()
+{
+ writeln("Hello, world!");
+}
+
+
+
+/*** типы и переменные ***/
+
+int a; // объявление переменной типа int (32 бита)
+float b = 12.34; // тип с плавающей точкой
+double c = 56.78; // тип с плавающей точкой (64 бита)
+
+/*
+ Численные типы в D, за исключением типов с плавающей точкой и типов
+ комплексных чисел, могут быть беззнаковыми.
+ В этом случае название типа начинается с префикса "u"
+*/
+uint d = 10; ulong e = 11;
+bool b = true; // логический тип
+char d = 'd'; // UTF-символ, 8 бит. D поддерживает UTF "из коробки"
+wchar e = 'é'; // символ UTF-16
+dchar f; // и даже UTF-32, если он вам зачем-то понадобится
+
+string s = "для строк есть отдельный тип, это не просто массив char-ов из Си";
+wstring ws = "поскольку у нас есть wchar, должен быть и wstring";
+dstring ds = "...и dstring, конечно";
+
+string кириллица = "Имена переменных должны быть в Unicode, но не обязательно на латинице.";
+
+typeof(a) b = 6; // typeof возвращает тип своего выражения.
+ // В результате, b имеет такой же тип, как и a
+
+// Тип переменной, помеченной ключевым словом auto,
+// присваивается компилятором исходя из значения этой переменной
+auto x = 1; // Например, тип этой переменной будет int.
+auto y = 1.1; // этой — double
+auto z = "Zed is dead!"; // а этой — string
+
+int[3] arr = [1, 2, 3]; // простой одномерный массив с фиксированным размером
+int[] arr2 = [1, 2, 3, 4]; // динамический массив
+int[string] aa = ["key1": 5, "key2": 6]; // ассоциативный массив
+
+/*
+ Строки и массивы в D — встроенные типы. Для их использования не нужно
+ подключать ни внешние, ни даже стандартную библиотеку, хотя в последней
+ есть множество дополнительных инструментов для работы с ними.
+ */
+immutable int ia = 10; // неизменяемый тип,
+ // обозначается ключевым словом immutable
+ia += 1; // — вызовет ошибку на этапе компиляции
+
+// перечислимый (enumerable) тип,
+// более правильный способ работы с константами в D
+enum myConsts = { Const1, Const2, Const3 };
+
+// свойства типов
+writeln("Имя типа : ", int.stringof); // int
+writeln("Размер в байтах : ", int.sizeof); // 4
+writeln("Минимальное значение : ", int.min); // -2147483648
+writeln("Максимальное значение : ", int.max); // 2147483647
+writeln("Начальное значение : ", int.init); // 0. Это значение,
+ // присвоенное по умолчанию
+
+// На самом деле типов в D больше, но все мы здесь описывать не будем,
+// иначе не уложимся в Y минут.
+
+
+
+/*** Приведение типов ***/
+
+// to!(имя типа)(выражение) - для большинства конверсий
+import std.conv : to; // функция "to" - часть стандартной библиотеки, а не языка
+double d = -1.75;
+short s = to!short(d); // s = -1
+
+/*
+ cast - если вы знаете, что делаете. Кроме того, это единственный способ
+ преобразования типов-указателей в "обычные" и наоборот
+*/
+void* v;
+int* p = cast(int*)v;
+
+// Для собственного удобства можно создавать псевдонимы
+// для различных встроенных объектов
+alias int newInt; // теперь можно обращаться к newInt так, как будто бы это int
+newInt a = 5;
+
+alias newInt = int; // так тоже допустимо
+alias uint[2] pair; // дать псевдоним можно даже сложным структурам данных
+
+
+
+/*** Операторы ***/
+
+int x = 10; // присваивание
+x = x + 1; // 11
+x -= 2; // 9
+x++; // 10
+++x; // 11
+x *= 2; // 22
+x /= 2; // 11
+x = x ^^ 2; // 121 (возведение в степень)
+x ^^= 2; // 1331 (то же самое)
+
+string str1 = "Hello";
+string str2 = ", world!";
+string hw = str1 ~ str2; // Конкатенация строк
+
+int[] arr = [1, 2, 3];
+arr ~= 4; // [1, 2, 3, 4] - добавление элемента в конец массива
+
+
+
+/*** Логика и сравнения ***/
+
+int x = 0; int y = 1;
+
+x == y; // false
+x > y; // false
+x < y; // true
+x >= y; // false
+x != y; // true. ! — логическое "не"
+x > 0 || x < 1; // true. || — логическое "или"
+x > 0 && x < 1; // false && — логическое "и"
+x ^ y // true; ^ - xor (исключающее "или")
+
+// Тернарный оператор
+auto y = (x > 10) ? 1 : 0; // если x больше 10, то y равен 1,
+ // в противном случае y равен нулю
+
+
+/*** Управляющие конструкции ***/
+
+// if - абсолютно привычен
+if (a == 1) {
+ // ..
+} else if (a == 2) {
+ // ..
+} else {
+ // ..
+}
+
+// switch
+switch (a) {
+ case 1:
+ // делаем что-нибудь
+ break;
+ case 2:
+ // делаем что-нибудь другое
+ break;
+ case 3:
+ // делаем что-нибудь еще
+ break;
+ default:
+ // default обязателен, без него будет ошибка компиляции
+ break;
+}
+
+// в D есть констукция "final switch". Она не может содержать секцию "defaul"
+// и применяется, когда все перечисляемые в switch варианты должны быть
+// обработаны явным образом
+
+int dieValue = 1;
+final switch (dieValue) {
+ case 1:
+ writeln("You won");
+ break;
+
+ case 2, 3, 4, 5:
+ writeln("It's a draw");
+ break;
+
+ case 6:
+ writeln("I won");
+ break;
+}
+
+// while
+while (a > 10) {
+ // ..
+ if (number == 42) {
+ break;
+ }
+}
+
+while (true) {
+ // бесконечный цикл
+}
+
+// do-while
+do {
+ // ..
+} while (a == 10);
+
+// for
+for (int number = 1; number < 11; ++number) {
+ writeln(number); // все абсолютно стандартно
+}
+
+for ( ; ; ) {
+ // секции могут быть пустыми. Это бесконечный цикл в стиле Си
+}
+
+// foreach - универсальный и самый "правильный" цикл в D
+foreach (element; array) {
+ writeln(element); // для простых массивов
+}
+
+foreach (key, val; aa) {
+ writeln(key, ": ", val); // для ассоциативных массивов
+}
+
+foreach (c; "hello") {
+ writeln(c); // hello. Поскольку строки - это вариант массива,
+ // foreach применим и к ним
+}
+
+foreach (number; 10..15) {
+ writeln(number); // численные интервалы можно указывать явным образом
+ // этот цикл выведет значения с 10 по 14, но не 15,
+ // поскольку диапазон не включает в себя верхнюю границу
+}
+
+// foreach_reverse - в обратную сторону
+auto container = [1, 2, 3];
+foreach_reverse (element; container) {
+ writefln("%s ", element); // 3, 2, 1
+}
+
+// foreach в массивах и им подобных структурах не меняет сами структуры
+int[] a = [1, 2 ,3 ,4 ,5];
+foreach (elem; array) {
+ elem *= 2; // сам массив останется неизменным
+}
+
+writeln(a); // вывод: [1, 2, 3, 4, 5] Т.е изменений нет
+
+// добавление ref приведет к тому, что массив будет изменяться
+foreach (ref elem; array) {
+ elem *= 2;
+}
+
+writeln(a); // [2, 4, 6, 8, 10]
+
+// foreach умеет рассчитывать индексы элементов
+int[] a = [1, 2, 3, 4, 5];
+foreach (ind, elem; array) {
+ writeln(ind, " ", elem); // через ind - доступен индекс элемента,
+ // а через elem - сам элемент
+}
+
+
+
+/*** Функции ***/
+
+test(42); // Что, вот так сразу? Разве мы где-то уже объявили эту функцию?
+
+// Нет, вот она. Это не Си, здесь объявление функции не обязательно должно быть
+// до первого вызова
+int test(int argument) {
+ return argument * 2;
+}
+
+
+// В D используется единый синтаксис вызова функций
+// (UFCS, Uniform Function Call Syntax), поэтому так тоже можно:
+int var = 42.test();
+
+// и даже так, если у функции нет аргументов:
+int var2 = 42.test;
+
+// можно выстраивать цепочки:
+int var3 = 42.test.test;
+
+/*
+ Аргументы в функцию передаются по значению (т.е. функция работает не с
+ оригинальными значениями, переданными ей, а с их локальными копиями.
+ Исключение составляют объекты классов, которые передаются по ссылке.
+ Кроме того, любой параметр можно передать в функцию по ссылке с помощью
+ ключевого слова "ref"
+*/
+int var = 10;
+
+void fn1(int arg) {
+ arg += 1;
+}
+
+void fn2(ref int arg) {
+ arg += 1;
+}
+
+fn1(var); // var все еще = 10
+fn2(var); // теперь var = 11
+
+// Возвращаемое значение тоже может быть auto,
+// если его можно "угадать" из контекста
+auto add(int x, int y) {
+ return x + y;
+}
+
+auto z = add(x, y); // тип int - компилятор вывел его автоматически
+
+// Значения аргументов по умолчанию
+float linearFunction(float k, float x, float b = 1)
+{
+ return k * x + b;
+}
+
+auto linear1 = linearFunction(0.5, 2, 3); // все аргументы используются
+auto linear2 = linearFunction(0.5, 2); // один аргумент пропущен, но в функции
+ // он все равно использован и равен 1
+
+// допускается описание вложенных функций
+float quarter(float x) {
+ float doubled(float y) {
+ return y * y;
+ }
+
+ return doubled(doubled(x));
+}
+
+// функции с переменным числом аргументов
+int sum(int[] a...)
+{
+ int s = 0;
+ foreach (elem; a) {
+ s += elem;
+ }
+ return s;
+}
+
+auto sum1 = sum(1);
+auto sum2 = sum(1,2,3,4);
+
+/*
+ модификатор "in" перед аргументами функций говорит о том, что функция имеет
+ право их только просматривать. При попытке модификации такого аргумента
+ внутри функции - получите ошибку
+*/
+float printFloat(in float a)
+{
+ writeln(a);
+}
+printFloat(a); // использование таких функций - самое обычное
+
+// модификатор "out" позволяет вернуть из функции несколько результатов
+// без посредства глобальных переменных или массивов
+uint remMod(uint a, uint b, out uint modulus)
+{
+ uint remainder = a / b;
+ modulus = a % b;
+ return remainder;
+}
+
+uint modulus; // пока в этой переменной ноль
+uint rem = remMod(5, 2, modulus); // наша "хитрая" функция, и теперь
+ // в modulus - остаток от деления
+writeln(rem, " ", modulus); // вывод: 2 1
+
+
+
+/*** Структуры, классы, базовое ООП ***/
+
+// Объявление структуры. Структуры почти как в Си
+struct MyStruct {
+ int a;
+ float b;
+
+ void multiply() {
+ return a * b;
+ }
+}
+
+MyStruct str1; // Объявление переменной с типом MyStruct
+str1.a = 10; // Обращение к полю
+str1.b = 20;
+auto result = str1.multiply();
+MyStruct str2 = {4, 8} // Объявление + инициализация в стиле Си
+auto str3 = MyStruct(5, 10); // Объявление + инициализация в стиле D
+
+
+// области видимости полей и методов - 3 способа задания
+struct MyStruct2 {
+ public int a;
+
+ private:
+ float b;
+ bool c;
+
+ protected {
+ float multiply() {
+ return a * b;
+ }
+ }
+ /*
+ в дополнение к знакомым public, private и protected, в D есть еще
+ область видимости "package". Поля и методы с этим атрибутом будут
+ доступны изо всех модулей, включенных в "пакет" (package), но не
+ за его пределами. package - это "папка", в которой может храниться
+ несколько модулей. Например, в "import.std.stdio", "std" - это
+ package, в котором есть модуль stdio (и еще множество других)
+ */
+ package:
+ string d;
+
+ /* помимо этого, имеется еще один модификатор - export, который позволяет
+ использовать объявленный с ним идентификатор даже вне самой программы !
+ */
+ export:
+ string description;
+}
+
+// Конструкторы и деструкторы
+struct MyStruct3 {
+ this() { // конструктор. Для структур его не обязательно указывать явно,
+ // в этом случае пустой конструктор добавляется компилятором
+ writeln("Hello, world!");
+ }
+
+
+ // а вот это конструкция - одна из интересных идиом и представляет собой
+ // конструктор копирования, т.е конструктор, возвращающий копию структуры.
+ // Работает только в структурах.
+ this(this)
+ {
+ return this;
+ }
+
+ ~this() { // деструктор, также необязателен
+ writeln("Awww!");
+ }
+}
+
+// Объявление простейшего класса
+class MyClass {
+ int a; // в D по умолчанию данные-члены являются public
+ float b;
+}
+
+auto mc = new MyClass(); // ...и создание его экземпляра
+auto mc2 = new MyClass; // ... тоже сработает
+
+// Конструктор
+class MyClass2 {
+ int a;
+ float b;
+
+ this(int a, float b) {
+ this.a = a; // ключевое слово "this" - ссылка на объект класса
+ this.b = b;
+ }
+}
+
+auto mc2 = new MyClass2(1, 2.3);
+
+// Классы могут быть вложенными
+class Outer
+{
+ int m;
+
+ class Inner
+ {
+ int foo()
+ {
+ return m; // можно обращаться к полям "внешнего" класса
+ }
+ }
+}
+
+// наследование
+class Base {
+ int a = 1;
+ float b = 2.34;
+
+
+ // это статический метод, т.е метод который можно вызывать, обращаясь
+ // к классу напрямую, а не через создание экземпляра объекта
+ static void multiply(int x, int y)
+ {
+ writeln(x * y);
+ }
+}
+
+Base.multiply(2, 5); // используем статический метод. Результат: 10
+
+class Derived : Base {
+ string c = "Поле класса - наследника";
+
+
+ // override означает то, что наследник предоставит свою реализацию метода,
+ // переопределив метод базового класса
+ override static void multiply(int x, int y)
+ {
+ super.multiply(x, y); // super - это ссылка на класс-предок, или базовый класс
+ writeln(x * y * 2);
+ }
+}
+
+auto mc3 = new Derived();
+writeln(mc3.a); // 1
+writeln(mc3.b); // 2.34
+writeln(mc3.c); // Поле класса - наследника
+
+// Финальный класс, наследовать от него нельзя
+// кроме того, модификатор final работает не только для классов, но и для методов
+// и даже для модулей !
+final class FC {
+ int a;
+}
+
+class Derived : FC { // это вызовет ошибку
+ float b;
+}
+
+// Абстрактный класс не может быть истанциирован, но может иметь наследников
+abstract class AC {
+ int a;
+}
+
+auto ac = new AC(); // это вызовет ошибку
+
+class Implementation : AC {
+ float b;
+
+ // final перед методом нефинального класса означает запрет возможности
+ // переопределения метода
+ final void test()
+ {
+ writeln("test passed !");
+ }
+}
+
+auto impl = new Implementation(); // ОК
+
+
+
+/*** Примеси (mixins) ***/
+
+// В D можно вставлять код как строку, если эта строка известна на этапе
+// компиляции. Например:
+void main() {
+ mixin(`writeln("Hello World!");`);
+}
+
+// еще пример
+string print(string s) {
+ return `writeln("` ~ s ~ `");`;
+}
+
+void main() {
+ mixin (print("str1"));
+ mixin (print("str2"));
+}
+
+
+
+/*** Шаблоны ***/
+
+/*
+ Шаблон функции. Эта функция принимает аргументы разных типов, которые
+ подставляются вместо T на этапе компиляции. "T" - это не специальный
+ символ, а просто буква. Вместо "T" может быть любое слово, кроме ключевого.
+ */
+void print(T)(T value) {
+ writefln("%s", value);
+}
+
+void main() {
+ print(42); // В одну и ту же функцию передается: целое
+ print(1.2); // ...число с плавающей точкой,
+ print("test"); // ...строка
+}
+
+// "Шаблонных" параметров может быть сколько угодно
+void print(T1, T2)(T1 value1, T2 value2) {
+ writefln(" %s %s", value1, value2);
+}
+
+void main() {
+ print(42, "Test");
+ print(1.2, 33);
+}
+
+// Шаблон класса
+class Stack(T)
+{
+ private:
+ T[] elements;
+
+ public:
+ void push(T element) {
+ elements ~= element;
+ }
+
+ void pop() {
+ --elements.length;
+ }
+
+ T top() const @property {
+ return elements[$ - 1];
+ }
+
+ size_t length() const @property {
+ return elements.length;
+ }
+}
+
+void main() {
+ /*
+ восклицательный знак - признак шаблона. В данном случае мы создаем
+ класс и указываем, что "шаблонное" поле будет иметь тип string
+ */
+ auto stack = new Stack!string;
+
+ stack.push("Test1");
+ stack.push("Test2");
+
+ writeln(stack.top);
+ writeln(stack.length);
+
+ stack.pop;
+ writeln(stack.top);
+ writeln(stack.length);
+}
+
+
+
+/*** Диапазоны (ranges) ***/
+
+/*
+ Диапазоны - это абстракция, которая позволяет легко использовать разные
+ алгоритмы с разными структурами данных. Вместо того, чтобы определять свои
+ уникальные алгоритмы для каждой структуры, мы можем просто указать для нее
+ несколько единообразных функций, определяющих, _как_ мы получаем доступ
+ к элементам контейнера, вместо того, чтобы описывать внутреннее устройство
+ этого контейнера. Сложно? На самом деле не очень.
+
+ Простейший вид диапазона - Input Range. Для того, чтобы превратить любой
+ контейнер в Input Range, достаточно реализовать для него 3 метода:
+ - empty - проверяет, пуст ли контейнер
+ - front - дает доступ к первому элементу контейнера
+ - popFront - удаляет из контейнера первый элемент
+*/
+struct Student
+{
+ string name;
+ int number;
+ string toString() {
+ return format("%s(%s)", name, number);
+ }
+}
+
+struct School
+{
+ Student[] students;
+}
+
+struct StudentRange
+{
+ Student[] students;
+
+ this(School school) {
+ this.students = school.students;
+ }
+
+ bool empty() {
+ return students.length == 0;
+ }
+
+ Student front() {
+ return students[0];
+ }
+
+ void popFront() {
+ students = students[1 .. $];
+ }
+}
+
+void main(){
+ auto school = School([
+ Student("Mike", 1),
+ Student("John", 2) ,
+ Student("Dan", 3)
+ ]);
+ auto range = StudentRange(school);
+ writeln(range); // [Mike(1), John(2), Dan(3)]
+ writeln(school.students.length); // 3
+ writeln(range.front()); // Mike(1)
+ range.popFront();
+ writeln(range.empty()); // false
+ writeln(range); // [John(2), Dan(3)]
+}
+/*
+ Смысл в том, что нам не так уж важно внутреннее устройство контейнера, если
+ у нас есть унифицированные методы доступа к его элементам.
+ Кроме Input Range в D есть и другие типы диапазонов, которые требуют
+ реализации большего числа методов, зато дают больше контроля. Это большая
+ тема и мы не будем в подробностях освещать ее здесь.
+
+ Диапазоны - это важная часть D, они используются в нем повсеместно.
+*/
+```
+## Что дальше?
+
+- [Официальный сайт](http://dlang.org/)
+- [Онлайн-книга](http://ddili.org/ders/d.en/)
+- [Официальная вики](http://wiki.dlang.org/)
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/erlang-ru.html.markdown b/ru-ru/erlang-ru.html.markdown
index 99ea79ee..69f81800 100644
--- a/ru-ru/erlang-ru.html.markdown
+++ b/ru-ru/erlang-ru.html.markdown
@@ -18,7 +18,7 @@ lang: ru-ru
% Пунктуационные знаки, используемые в Erlang:
% Запятая (`,`) разделяет аргументы в вызовах функций, структурах данных и
% образцах.
-% Точка (`.`) (с пробелом после них) разделяет функции и выражения в
+% Точка (`.`) (с пробелом после неё) разделяет функции и выражения в
% оболочке.
% Точка с запятой (`;`) разделяет выражения в следующих контекстах:
% формулы функций, выражения `case`, `if`, `try..catch` и `receive`.
diff --git a/ru-ru/forth-ru.html.markdown b/ru-ru/forth-ru.html.markdown
new file mode 100644
index 00000000..05316578
--- /dev/null
+++ b/ru-ru/forth-ru.html.markdown
@@ -0,0 +1,240 @@
+---
+language: forth
+contributors:
+ - ["Horse M.D.", "http://github.com/HorseMD/"]
+translators:
+ - ["Dmitrii Kuznetsov", "https://github.com/torgeek"]
+filename: learnforth-ru.fs
+lang: ru-ru
+---
+
+Форт создан Чарлзом Муром в 70-е годы. Это императивный, стековый язык программирования и среда исполнения программ. Использовался в таких проектах как Open Firmware. Продолжает применятся в проектах. Применяется в НАСА.
+
+Внимание: эта материал использует реализацию Форта - Gforth, но большая часть написанного будет работать в других средах.
+
+```
+\ Это комментарий
+( Это тоже комментарий, но использыется для предоределённых слов )
+
+\ --------------------------------- Прекурсор --------------------------------
+
+\ Всё программирование на Форте заключается в манипулировании
+\ параметрами на стеке.
+5 2 3 56 76 23 65 \ ok
+
+\ Эти числа добавляются в стек слева направо
+.s \ <7> 5 2 3 56 76 23 65 ok
+
+\ В Форте всё - это слова-команды или числа. Слова разделяются любым числом
+\ пробелов и переходов на новую строку. Длина слова не больше 31 литеры.
+
+\ ---------------------------- Базовая арифметика ----------------------------
+
+\ Арифметика (фактически все ключевые слова требуют данных) - это манипуляция
+\ данными на стеке.
+5 4 + \ ok
+
+\ `.` показывает верхнее значение в стеке:
+. \ 9 ok
+
+\ Ещё примеры арифметических выражений:
+6 7 * . \ 42 ok
+1360 23 - . \ 1337 ok
+12 12 / . \ 1 ok
+13 2 mod . \ 1 ok
+
+99 negate . \ -99 ok
+-99 abs . \ 99 ok
+52 23 max . \ 52 ok
+52 23 min . \ 23 ok
+
+\ --------------------------- Манипуляции со стеком ---------------------------
+
+\ Естественно, когда мы работаем со стеком, то используем
+\ больше полезных методов:
+
+3 dup - \ дублировать верхний элемент в стеке
+ \ (1-й становится эквивалентным 2-му): 3 - 3
+2 5 swap / \ поменять местами верхний элемент со 2-м элементом: 5 / 2
+6 4 5 rot .s \ сменять по очереди 3-и верхних элемента: 4 5 6
+4 0 drop 2 / \ снять верхний элемент (не печатается на экране): 4 / 2
+1 2 3 nip .s \ снять второй элемент (подобно исключению элемента): 1 3
+
+\ ------------------ Более продвинутые манипуляции со стеком ------------------
+
+1 2 3 4 tuck \ дублировать верхний елемент стека во вторую позицию:
+ \ 1 2 4 3 4 ok
+1 2 3 4 over \ диблировать второй елемент наверх стека:
+ \ 1 2 3 4 3 ok
+1 2 3 4 2 roll \ *переместить* элемент в заданной позиции наверх стека:
+ \ 1 3 4 2 ok
+1 2 3 4 2 pick \ *дублировать* элемент в заданной позиции наверх:
+ \ 1 2 3 4 2 ok
+
+\ Внимание! Обращения к стеку индексируются с нуля.
+
+\ --------------------------- Создание новых слов -----------------------------
+
+\ Определение новых слов через уже известные. Двоеточие `:` переводит Форт
+\ в режим компиляции выражения, которое заканчивается точкой с запятой `;`.
+: square ( n -- n ) dup * ; \ ok
+5 square . \ 25 ok
+
+\ Мы всегда можем посмотреть, что содержится в слове:
+see square \ : square dup * ; ok
+
+\ -------------------------------- Зависимости --------------------------------
+
+\ -1 == true, 0 == false. Однако, некоторые ненулевые значения
+\ обрабатываются как true:
+42 42 = \ -1 ok
+12 53 = \ 0 ok
+
+\ `if` это компилируемое слово. `if` <stuff to do> `then` <rest of program>.
+: ?>64 ( n -- n ) dup 64 > if ." Больше чем 64!" then ;
+\ ok
+100 ?>64
+\ Больше чем 64! ok
+
+\ Else:
+: ?>64 ( n -- n ) dup 64 > if ." Больше чем 64!" else ." меньше чем 64!" then ;
+100 ?>64 \ Больше чем 64! ok
+20 ?>64 \ меньше чем 64! ok
+
+\ ------------------------------------ Циклы -----------------------------------
+
+\ `do` это тоже компилируемое слово.
+: myloop ( -- ) 5 0 do cr ." Hello!" loop ; \ ok
+myloop
+\ Hello!
+\ Hello!
+\ Hello!
+\ Hello!
+\ Hello! ok
+
+\ `do` предполагает наличие двух чисел на стеке: конечное и начальное число.
+
+\ Мы можем назначить в цикле переменную `i` для значения индекса:
+: one-to-12 ( -- ) 12 0 do i . loop ; \ ok
+one-to-12 \ 0 1 2 3 4 5 6 7 8 9 10 11 12 ok
+
+\ `?do` работает подобным образом, за исключением пропуска начального
+\ и конечного значения индекса цикла.
+: squares ( n -- ) 0 ?do i square . loop ; \ ok
+10 squares \ 0 1 4 9 16 25 36 49 64 81 ok
+
+\ Изменение "шага" цикла проиводится командой `+loop`:
+: threes ( n n -- ) ?do i . 3 +loop ; \ ok
+15 0 threes \ 0 3 6 9 12 ok
+
+\ Запуск бесконечного цикла - `begin` <stuff to do> <flag> `until`:
+: death ( -- ) begin ." Вы всё ещё здесь?" 0 until ; \ ok
+
+\ ---------------------------- Переменные и память ----------------------------
+
+\ Используйте `variable`, что бы объявить `age` в качестве переменной.
+variable age \ ok
+
+\ Затем мы запишем число 21 в переменную 'age' (возраст) словом `!`.
+21 age ! \ ok
+
+\ В заключении мы можем напечатать значение переменной прочитав его словом `@`,
+\ которое добавит значение на стек или использовать слово `?`,
+\ что бы прочитать и распечатать в одно действие.
+age @ . \ 21 ok
+age ? \ 21 ok
+
+\ Константы объявляются аналогично, за исключем того, что мы не должны
+\ беспокоиться о выделении адреса в памяти:
+100 constant WATER-BOILING-POINT \ ok
+WATER-BOILING-POINT . \ 100 ok
+
+\ ---------------------------------- Массивы ----------------------------------
+
+\ Создание массива похоже на объявление переменной, но нам нужно выделить
+\ больше памяти.
+
+\ Вы можете использовать слова `2 cells allot` для создания массива
+\ размером 3 элемента:
+variable mynumbers 2 cells allot \ ok
+
+\ Инициализировать все значения в 0
+mynumbers 3 cells erase \ ok
+
+\ В качестве альтернативы мы можем использовать `fill`:
+mynumbers 3 cells 0 fill
+
+\ или мы можем пропустить все слова выше и инициализировать массив
+\ нужными значениями:
+create mynumbers 64 , 9001 , 1337 , \ ok (the last `,` is important!)
+
+\ ... что эквивалентно:
+
+\ Ручная запись значений по индексам ячеек:
+64 mynumbers 0 cells + ! \ ok
+9001 mynumbers 1 cells + ! \ ok
+1337 mynumbers 2 cells + ! \ ok
+
+\ Чтение значений по индексу:
+0 cells mynumbers + ? \ 64 ok
+1 cells mynumbers + ? \ 9001 ok
+
+\ Мы можем просто сделать собственное слово для манипуляции массивом:
+: of-arr ( n n -- n ) cells + ; \ ok
+mynumbers 2 of-arr ? \ 1337 ok
+
+\ Которую тоже можно использовать для записи значений:
+20 mynumbers 1 of-arr ! \ ok
+mynumbers 1 of-arr ? \ 20 ok
+
+\ ------------------------------ Стек возвратов ------------------------------
+
+\ Стек возвратов используется для удержания ссылки,
+\ когда одно слово запускает другое, например, в цикле.
+
+\ Мы всегда видим это, когда используем `i`, которая возвращает дубль верхнего
+\ значения стека. `i` это эквивалент `r@`.
+: myloop ( -- ) 5 0 do r@ . loop ; \ ok
+
+\ Так же как при чтении мы можем добавить ссылку в стек возвратов и удалить её:
+5 6 4 >r swap r> .s \ 6 5 4 ok
+
+\ Внимание: так как Форт использует стек возвратов для указателей на слово `>r`
+\ следует всегда пользоваться `r>`.
+
+\ ---------------- Операции над числами с плавающей точкой --------------------
+
+\ Многие фортовцы стараются избегать использование слов с вещественными числами.
+8.3e 0.8e f+ f. \ 9.1 ok
+
+\ Обычно мы просто используем слово 'f', когда обращаемся к вещественным числам:
+variable myfloatingvar \ ok
+4.4e myfloatingvar f! \ ok
+myfloatingvar f@ f. \ 4.4 ok
+
+\ ---------- В завершение несколько полезных замечаний и слов -----------------
+
+\ Указание несуществующего слова очистит стек. Тем не менее, есть специальное
+\ слово для этого:
+clearstack
+
+\ Очистка экрана:
+page
+
+\ Загрузка форт-файла:
+\ s" forthfile.fs" included
+
+\ Вы можете вывести список всех слов словаря Форта (это большой список!):
+words
+
+\ Выход из Gforth:
+bye
+
+```
+
+##Готовы к большему?
+
+* [Начала Форта (англ.)](http://www.forth.com/starting-forth/)
+* [Простой Форт (англ.)](http://www.murphywong.net/hello/simple.htm)
+* [Мышление Форта (англ.)](http://thinking-forth.sourceforge.net/)
+* [Учебники Форта (рус.)](http://wiki.forth.org.ru/УчебникиФорта)
diff --git a/ru-ru/go-ru.html.markdown b/ru-ru/go-ru.html.markdown
index e06ae9bd..6c8622cc 100644
--- a/ru-ru/go-ru.html.markdown
+++ b/ru-ru/go-ru.html.markdown
@@ -35,6 +35,7 @@ package main
// Import предназначен для указания зависимостей этого файла.
import (
"fmt" // Пакет в стандартной библиотеке Go
+ "io/ioutil" // Реализация функций ввод/ввывода.
"net/http" // Да, это веб-сервер!
"strconv" // Конвертирование типов в строки и обратно
m "math" // Импортировать math под локальным именем m.
@@ -321,6 +322,14 @@ func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Обработка запроса и отправка данных методом из http.ResponseWriter
w.Write([]byte("You learned Go in Y minutes!"))
}
+
+func requestServer() {
+ resp, err := http.Get("http://localhost:8080")
+ fmt.Println(err)
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ fmt.Printf("\nWebserver said: `%s`", string(body))
+}
```
## Что дальше
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
+ &= "Да & да"
+
+/ выведет 'Да &amp; да'
+
+/
+ Чтобы выполнять 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
new file mode 100644
index 00000000..120981b9
--- /dev/null
+++ b/ru-ru/html-ru.html.markdown
@@ -0,0 +1,129 @@
+---
+language: 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(гипертекстовый язык разметки).
+Это язык используют для написания страниц для World Wide Web(всемирной паутины).
+Это язык разметки позволяет писать веб-страниц с помощью кода, чтобы определять,
+как должны быть отображены текст и данные.
+На самом деле, HTML файлы представляют собой простые текстовые файлы.
+Что такое разметка? Это способ организации данных страницы,
+путем открытия и закрытия тегов(помещая данные внутрь этих тегов).
+Эта разметка служит, чтобы придать значение тексту, который он окружает.
+Как и в других языках программирования, HTML имеет много версий. Здесь мы будем говорить о HTML5.
+
+
+**Примечание:** Вы можете тестировать различные теги и элементы по мере продвижения
+через учебник на сайте, как [codepen](http://codepen.io/pen/) для того, чтобы увидеть
+их влияние, понять, как они работают и ознакомиться с языком.
+В данной статье рассматривается в основном HTML синтаксис и некоторые полезные советы.
+
+```html
+<!-- Комментарии заключаются как эта лини\! -->
+
+<!-- #################### Теги #################### -->
+
+<!-- Ниже приведен пример HTML-файл, который мы будем анализировать. -->
+
+<!doctype html>
+ <html>
+ <head>
+ <title>Мой сайт</title>
+ </head>
+ <body>
+ <h1>Привет, мир!</h1>
+ <a href = "http://codepen.io/anon/pen/xwjLbZ">
+ Переходите сюда, чтоб посмотреть как это выглядит.
+ </a>
+ <p>Это параграф.</p>
+ <p>Это другой параграф.</p>
+ <ul>
+ <li>Это элемент не нумерованного списка (маркированный список)</li>
+ <li>Это другой элемент</li>
+ <li>Это последний элемент в списке</li>
+ </ul>
+ </body>
+ </html>
+
+<!-- HTML-файл всегда начинается с указанием браузеру, что страница это HTML. -->
+<!doctype html>
+
+<!-- После этого, страница начинается с <html> тега. -->
+<html>
+
+<!-- страница будет закрыта в конце с помощью тега </html>. -->
+</html>
+
+<!-- Ничто не должно появиться после этого заключительного тега. -->
+
+<!-- Внутри (между открывающим и закрывающим тегами <html> </ html>), мы находим: -->
+
+<!-- Заголовок определяется <head> (it он должен быть закрыт </head>). -->
+<!-- Заголовок содержит описание и дополнительную информацию, которая не отображается; это метаданные. -->
+
+<head>
+ <title>Мой сайт</title><!-- Тег <title> указывает браузеру заголовок, чтобы показать в строке заголовка названия и вкладки браузера окна. -->
+</head>
+
+<!-- После секция <head>, находится секция - <body> -->
+<!-- До этого момента, ничего описаное не будет отображаться в окне браузера. -->
+<!-- Мы должны наполнить <body> содержанием, которое будет отображаться. -->
+
+<body>
+ <h1>Hello, world!</h1> <!-- Тег h1 создает заголовок. -->
+ <!-- Так же существуют другие заголовки от имеющего большее значение <h1> по убыванию к <h6>. -->
+ <a href = "http://codepen.io/anon/pen/xwjLbZ">Переходите сюда, чтоб посмотреть как это выглядит.</a>
+ <!--гиперссылка на URL, заданнf атрибутом href="" -->
+ <p>Это параграф.</p> <!-- Тег <p> позволяет нам добавдять текст на странице HTML. -->
+ <p>Это другой параграф.</p>
+ <ul> <!-- Тег <ul> создает маркированный список. -->
+ <!-- Для того, чтобы иметь пронумерованный список лучше использовать <ol>
+ тогда первый элемент будет иметь значение 1. для второго элемента, 2. и так далее. -->
+ <li>Это элемент в не нумерованном списке (маркированный список)</li>
+ <li>Это еще один элемент</li>
+ <li>И это последний пункт в списке</li>
+ </ul>
+</body>
+
+<!-- Вот так просто можно создать HTML страницу. -->
+
+<!--Но можно добавить множество дополнительных типов HTML тегов. -->
+
+<!-- Для вставки картинки -->
+<img src="http://i.imgur.com/XWG0O.gif"/> <!-- Источник изображения указывается с помощью атрибута src="" -->
+<!-- Источником может быть URL или даже путь к файлу на вашем компьютере. -->
+
+<!-- Кроме того, можно создать таблицу. -->
+
+<table> <!-- Мы открыли <table> элемент. -->
+ <tr> <!-- <tr> позволяет создать ряд. -->
+ <th>Первый заголовок</th> <!-- <th> позволяет дать название для столбца таблицы. -->
+ <th>Второй заголовок</th>
+ </tr>
+ <tr>
+ <td>Первый ряд, первая колонка</td> <!-- <td> позволяет нам создать ячейку таблицы. -->
+ <td>Первый ряд, вторая колонка</td>
+ </tr>
+ <tr>
+ <td>Второй ряв, первая колонка</td>
+ <td>Второй ряд, вторая колонка</td>
+ </tr>
+</table>
+
+```
+
+## Применение
+
+HTML файлы имеют окончание(расширение) `.html`.
+
+## Узнать больше
+
+* [википедиа](https://ru.wikipedia.org/wiki/HTML)
+* [HTML учебник](https://developer.mozilla.org/ru/docs/Web/HTML)
+* [htmlbook](http://htmlbook.ru/)
diff --git a/ru-ru/java-ru.html.markdown b/ru-ru/java-ru.html.markdown
index 005495cc..1aff801c 100644
--- a/ru-ru/java-ru.html.markdown
+++ b/ru-ru/java-ru.html.markdown
@@ -1,15 +1,16 @@
---
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 - это объектно ориентированный язык программирования общего назначения,
+Java - это объектно-ориентированный язык программирования общего назначения,
основанный на классах и поддерживающий параллельное программирование.
[Подробнее читайте здесь.](http://docs.oracle.com/javase/tutorial/java/index.html)
@@ -43,17 +44,41 @@ public class LearnJavaRu {
" Double: " + 3.14 +
" Boolean: " + true);
- // Чтобы напечатать что-либо не заканчивая переводом строки
- // используется System.out.print.
+ // Чтобы печатать что-либо, не заканчивая переводом строки,
+ // используйте System.out.print.
System.out.print("Hello ");
System.out.print("World");
+ // Используйте System.out.printf() для печати с форматированием
+ System.out.printf("pi = %.5f", Math.PI); // => pi = 3.14159
///////////////////////////////////////
- // Типы и Переменные
+ // Переменные
///////////////////////////////////////
+ /*
+ * Объявление переменных
+ */
// Переменные объявляются с использованием <тип> <имя>
+ int fooInt;
+ // Одновременное объявление нескольких переменных одного типа
+ // <type> <name1>, <name2>, <name3>
+ int fooInt1, fooInt2, fooInt3;
+
+ /*
+ * Инициализация переменных
+ */
+
+ // объявление и инициализация переменной <type> <name> = <val>
+ int fooInt = 1;
+ int fooInt1, fooInt2, fooInt3;
+ // инициализация нескольких переменных одного типа
+ // <type> <name1>, <name2>, <name3> = <val>
+ fooInt1 = fooInt2 = fooInt3 = 1;
+
+ /*
+ * Типы переменных
+ */
// Byte - 8-битное целое число.
// (-128 <= byte <= 127)
byte fooByte = 100;
@@ -247,7 +272,7 @@ public class LearnJavaRu {
// Switch Case
// switch работает с типами byte, short, char и int.
// Также он работает с перечислениями,
- // классом String и с некоторыми классами-обертками над
+ // классом String (с Java 7) и с некоторыми классами-обертками над
// примитивными типами: Character, Byte, Short и Integer.
int month = 3;
String monthString;
@@ -319,7 +344,7 @@ public class LearnJavaRu {
System.out.println("trek info: " + trek.toString());
} // Конец метода main.
-} // Конец класса LearnJava.
+} // Конец класса LearnJavaRu.
// Вы можете включать другие, не публичные классы в .java файл.
@@ -362,7 +387,7 @@ class Bicycle {
// Классы в Java часто реализуют сеттеры и геттеры для своих полей.
// Синтаксис определения метода:
- // <модификатор> <тип возвращаемого значения> <имя>(<аргументы>)
+ // <модификатор доступа> <тип возвращаемого значения> <имя метода>(<аргументы>)
public int getCadence() {
return cadence;
}
@@ -424,10 +449,10 @@ class PennyFarthing extends Bicycle {
// Интерфейсы
// Синтаксис определения интерфейса:
-// <модификатор доступа> interface <имя> extends <базовый интерфейс> {
-// // Константы
-// // Определение методов.
-//}
+// <модификатор доступа> interface <имя интерфейса> extends <базовый интерфейс> {
+// // Константы
+// // Определение методов
+// }
// Пример - Еда:
public interface Edible {
@@ -451,7 +476,7 @@ public class Fruit implements Edible, Digestible {
}
}
-// В Java Вы можете наследоватьтолько один класс, однако можете реализовывать
+// В Java Вы можете наследовать только один класс, однако можете реализовывать
// несколько интерфейсов. Например:
public class ExampleClass extends ExampleClassParent implements InterfaceOne, InterfaceTwo {
public void InterfaceOneMethod() {
diff --git a/ru-ru/javascript-ru.html.markdown b/ru-ru/javascript-ru.html.markdown
index e7398c88..1f1ffce6 100644
--- a/ru-ru/javascript-ru.html.markdown
+++ b/ru-ru/javascript-ru.html.markdown
@@ -22,8 +22,8 @@ Google Chrome, становится все более популярной.
```js
// Си-подобные комментарии. Однострочные комментарии начинаются с двух символов слэш,
-/* а многострочные комментарии начинаются с звёздочка-слэш
- и заканчиваются символами слэш-звёздочка */
+/* а многострочные комментарии начинаются с последовательности слэш-звёздочка
+ и заканчиваются символами звёздочка-слэш */
// Инструкции могут заканчиваться точкой с запятой ;
doStuff();
@@ -330,7 +330,7 @@ function sayHelloInFiveSeconds(name) {
sayHelloInFiveSeconds("Адам"); // Через 5 с откроется окно «Привет, Адам!»
///////////////////////////////////
-// 5. Подробнее об объектах; конструкторы и прототипы
+// 5. Подробнее об объектах; Конструкторы и Прототипы
// Объекты могут содержать в себе функции.
var myObj = {
@@ -359,6 +359,7 @@ myFunc(); // = undefined
// И наоборот, функция может быть присвоена объекту и получать доступ к нему
// через this, даже если она не была прикреплена к нему при объявлении.
var myOtherFunc = function() {
+ return this.myString.toUpperCase();
}
myObj.myOtherFunc = myOtherFunc;
myObj.myOtherFunc(); // = "ПРИВЕТ, МИР!"
@@ -470,9 +471,6 @@ myNumber === myNumberObj; // = false
if (0) {
// Этот код не выполнится, потому что 0 - это ложь.
}
-if (Number(0)) {
- // Этот код *выполнится*, потому что Number(0) истинно.
-}
// Впрочем, объекты-обёртки и встроенные типы имеют общие прототипы,
// поэтому вы можете расширить функционал строк, например:
diff --git a/ru-ru/json-ru.html.markdown b/ru-ru/json-ru.html.markdown
new file mode 100644
index 00000000..52af3696
--- /dev/null
+++ b/ru-ru/json-ru.html.markdown
@@ -0,0 +1,61 @@
+---
+language: json
+filename: learnjson-ru.json
+contributors:
+ - ["Anna Harren", "https://github.com/iirelu"]
+ - ["Marco Scannadinari", "https://github.com/marcoms"]
+translators:
+ - ["Dmitry Bessonov", "https://github.com/TheDmitry"]
+lang: ru-ru
+---
+
+JSON - это очень простой формат обмена данными, и это будет самый легкий
+курс из когда-либо представленных "Learn X in Y Minutes".
+
+В чистом виде у JSON нет фактических комментариев, но большинство парсеров примут
+комментарии в Си-стиле (//, /\* \*/). Для таких целей, конечно, все правильно
+будет на 100% с точки зрения JSON. К счастью, в нашем случае данные скажут сами за себя.
+
+```json
+{
+ "ключ": "значение",
+
+ "ключи": "должны всегда заключаться в двойные кавычки",
+ "числа": 0,
+ "строки": "Пρивет, миρ. Допускаются все unicode-символы вместе с \"экранированием\".",
+ "содержит логический тип?": true,
+ "ничего": null,
+
+ "большое число": 1.2e+100,
+
+ "объекты": {
+ "комментарий": "Большинство ваших структур будут представлять из себя объекты.",
+
+ "массив": [0, 1, 2, 3, "Массивы могут содержать в себе любой тип.", 5],
+
+ "другой объект": {
+ "комментарий": "Они могут быть вложенными, и это очень полезно."
+ }
+ },
+
+ "бессмыслие": [
+ {
+ "источники калия": ["бананы"]
+ },
+ [
+ [1, 0, 0, 0],
+ [0, 1, 0, 0],
+ [0, 0, 1, "нео"],
+ [0, 0, 0, 1]
+ ]
+ ],
+
+ "альтернативный стиль": {
+ "комментарий": "проверьте это!"
+ , "позиция запятой": "неважна, хоть и перед значением, все равно правильно"
+ , "еще один комментарий": "как хорошо"
+ },
+
+ "это было недолго": "И вы справились. Теперь вы знаете все о JSON."
+}
+```
diff --git a/ru-ru/kotlin-ru.html.markdown b/ru-ru/kotlin-ru.html.markdown
new file mode 100644
index 00000000..21940e41
--- /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 и браузера. Язык полностью cjdvtcnbv 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/lua-ru.html.markdown b/ru-ru/lua-ru.html.markdown
index 6f515975..da9ced6a 100644
--- a/ru-ru/lua-ru.html.markdown
+++ b/ru-ru/lua-ru.html.markdown
@@ -1,5 +1,5 @@
---
-language: lua
+language: Lua
filename: learnlua-ru.lua
contributors:
- ["Tyler Neylon", "http://tylerneylon.com/"]
diff --git a/ru-ru/markdown-ru.html.markdown b/ru-ru/markdown-ru.html.markdown
index eb8e4881..ff7a0cc3 100644
--- a/ru-ru/markdown-ru.html.markdown
+++ b/ru-ru/markdown-ru.html.markdown
@@ -2,55 +2,77 @@
language: markdown
contributors:
- ["Dan Turkel", "http://danturkel.com/"]
+ - ["Jacob Ward", "http://github.com/JacobCWard/"]
+translators:
- ["Pirogov Alexey", "http://twitter.com/alex_pir"]
+ - ["Andre Polykanine", "https://github.com/Oire"]
filename: markdown-ru.md
lang: ru-ru
---
Язык разметки Markdown создан Джоном Грубером (англ. John Gruber)
-и Аароном Шварцем (англ. Aaron H. Swartz) в 2004 году.
+в 2004 году.
Авторы задавались целью создать максимально удобочитаемый
и удобный в публикации облегчённый язык разметки,
пригодный для последующего преобразования в HTML
(а также и в другие форматы).
+Также реализации Markdown варьируют в зависимости от парсера.
+В этом руководстве будет указано, какие функции универсальны для языка,
+а какие зависят от конкретного парсера.
+
+- [HTML-элементы](#html-elements)
+- [Заголовки](#headings)
+- [Простейшая стилизация текста](#simple-text-styles)
+- [Абзацы](#paragraphs)
+- [Списки](#lists)
+- [Блоки кода](#code-blocks)
+- [Горизонтальный разделитель](#horizontal-rule)
+- [Ссылки](#links)
+- [Изображения](#images)
+- [Разное](#miscellany)
+
+## HTML-элементы
+Markdown является надмножеством HTML, поэтому любой HTML-файл является
+корректным документом Markdown.
+
```markdown
-<!-- Markdown является надмножеством HTML, поэтому любой HTML-файл является
-валидным документом Markdown, что позволяет использовать напрямую
+<!-- Это позволяет использовать напрямую
любые элементы HTML-разметки, такие, например, как этот комментарий.
Встроенные в документ HTML-элементы не затрагиваются парсером Markdown
-и попадают в итоговый HTML без изменений. Однако, следует понимать,
+и попадают в итоговый HTML без изменений. Однако следует понимать,
что эта же особенность не позволяет использовать разметку Markdown внутри
HTML-элементов -->
-<!-- Ещё одна особенность формата Markdown состоит в том, что поддерживаемые
-возможности разметки зависят от конкретной реализации парсера. В данном
-руководстве возможности, поддерживаемые лишь определёнными парсерами,
-сопровождаются соответствующими примечаниями. -->
-
-<!-- Заголовки -->
+## Заголовки
-<!-- HTML-элементы от <h1> до <h6> размечаются очень просто:
+HTML-элементы от <h1> до <h6> размечаются очень просто:
текст, который должен стать заголовком, предваряется
-соответствующим количеством символов "#": -->
+соответствующим количеством символов "#":
+
+```markdown
# Это заголовок h1
## Это заголовок h2
### Это заголовок h3
#### Это заголовок h4
##### Это заголовок h5
###### Это заголовок h6
+```
+Markdown позволяет размечать заголовки <h1> и <h2> ещё одним способом:
-<!-- Markdown позволяет размечать заголовки <h1> и <h2> ещё одним способом: -->
+```markdown
Это заголовок h1
================
А это заголовок h2
------------------
+```
-<!-- Простейшая стилизация текста -->
+## Простейшая стилизация текста
-<!-- Текст легко сделать полужирным и/или курсивным: -->
+Текст легко сделать полужирным и/или курсивным:
+```markdown
*Этот текст будет выведен курсивом.*
_Так же, как этот._
@@ -60,44 +82,58 @@ __И этот тоже.__
***Полужирный курсив.***
**_И тут!_**
*__И даже здесь!__*
+```
-<!-- В Github Flavored Markdown (версии Markdown, использующейся в Github,
-для рендеринга Markdown-документов) текст можно сделать зачёркнутым: -->
+В Github Flavored Markdown, стандарте, который используется в Github,
+текст также можно сделать зачёркнутым:
+```markdown
~~Зачёркнутый текст.~~
+```
+
+## Абзацы
+
+Абзацами являются любые строки, следующие друг за другом.
+Разделяются же абзацы одной или несколькими пустыми строками:
-<!-- Абзацами являются любые строки, следующие друг за другом.
-Разделяются же абзацы одной или несколькими пустыми строками: -->
+```markdown
+Это абзац. Я печатаю в абзаце, разве это не прикольно?
-Это абзац. Всё предельно просто.
+А тут уже абзац №2.
+Эта строка всё ещё относится к абзацу №2!
-А тут уже параграф №2.
-Эта строка всё ещё относится к параграфу №2!
+О, а вот это уже абзац №3!
+```
-О, а вот это уже параграф №3!
+Для вставки принудительных переносов можно завершить абзац двумя дополнительными пробелами:
-<!-- Для вставки принудительных переносов можно использовать HTML-тэг <br/>: -->
+```markdown
+Эта строка завершается двумя пробелами (выделите, чтобы увидеть!).
-Принудительный <br/> перенос!
+Над этой строкой есть <br />!
+```
-<!-- Цитаты размечаются с помощью символа ">": -->
+Цитаты размечаются с помощью символа «>»:
+```markdown
> Это цитата. В цитатах можно
-> принудительно переносить строки, вставляя ">" в начало каждой следующей строки. А можно просто оставлять достаточно длинными, и такие длинные строки будут перенесены автоматически.
+> принудительно переносить строки, вставляя «>» в начало каждой следующей строки. А можно просто оставлять их достаточно длинными, и такие длинные строки будут перенесены автоматически.
> Разницы между этими двумя подходами к переносу строк нет, коль скоро
-> каждая строка начинается с символа ">"
+> каждая строка начинается с символа «>»
> А ещё цитаты могут быть многоуровневыми:
>> как здесь
>>> и здесь :)
> Неплохо?
+```
-<!-- Списки -->
-<!-- Маркированные списки размечаются вставкой в начало каждого элемента
-одного из символов "*", "+" или "-":
-(символ должен быть одним и тем же для всех элементов) -->
+## Списки
+Маркированные списки размечаются вставкой в начало каждого элемента
+одного из символов «*», «+» или «-»:
+(символ должен быть одним и тем же для всех элементов)
+```markdown
* Список,
* Размеченный
* Звёздочками
@@ -113,167 +149,207 @@ __И этот тоже.__
- Список,
- Размеченный
- Дефисами
+```
-<!-- В нумерованных списках каждая строка начинается
-с числа и точки вслед за ним: -->
+В нумерованных списках каждая строка начинается
+с числа и точки вслед за ним:
+```markdown
1. Первый элемент
2. Второй элемент
3. Третий элемент
+```
-<!-- Заметьте, нумеровать элементы корректно необязательно. Достаточно указать
-любое число в начале каждого элемента и рендер пронумерует элементы сам!
-Правда, злоупотреблять этим не стоит :) -->
+Заметьте, нумеровать элементы корректно необязательно. Достаточно указать
+любое число в начале каждого элемента, и парсер пронумерует элементы сам!
+Правда, злоупотреблять этим не стоит :)
+```markdown
1. Первый элемент
1. Второй элемент
1. Третий элемент
-<!-- (Этот список будет отрендерен так же, как и предыдущий!) -->
+```
+(Этот список будет отображён так же, как и предыдущий!)
-<!-- Списки могут быть вложенными: -->
+Списки могут быть вложенными:
+```markdown
1. Введение
2. Начало работы
3. Примеры использования
* Простые
* Сложные
4. Заключение
+```
+
+Можно даже делать списки задач. Блок ниже создаёт HTML-флажки.
-<!-- Блоки с исходным кодом -->
-<!-- Фрагменты исходного кода выделяются очень просто - каждая строка блока должна иметь отступ в четыре пробела либо в один символ табуляции -->
+```markdown
+Для отметки флажка используйте «x»
+- [ ] Первая задача
+- [ ] Вторая задача
+Этот флажок ниже будет отмечен
+- [x] Задача была завершена
+```
+## Блоки кода
+
+Фрагменты исходного кода (обычно отмечаемые тегом `<code>`) выделяются просто:
+каждая строка блока должна иметь отступ в четыре пробела либо в один символ табуляции.
+
+```markdown
Это код,
- причём - многострочный
+ причём многострочный
+```
-<!-- Дополнительные отступы в коде следует делать с помощью четырёх пробелов: -->
+Вы также можете делать дополнительные отступы, добавляя символы табуляции
+или по четыре пробела:
+```markdown
my_array.each do |item|
puts item
end
+```
-<!-- Иногда бывает нужно вставить фрагмент кода прямо в строку текста,
+Иногда бывает нужно вставить фрагмент кода прямо в строку текста,
не выделяя код в блок. Для этого фрагменты кода нужно обрамлять
-символами "`": -->
+символами «`»:
-Например, можно выделить имя функции `go_to()` прямо посреди текста.
+```markdown
+Ваня даже не знал, что делает функция `go_to()`!
+```
-<!-- Github Flavored Markdown позволяет указать для блока кода синтаксис оного.
-В этом случае синтаксис внутри блока будет подсвечен. Пример: -->
+В Github Flavored Markdown для блоков кода можно использовать
+специальный синтаксис:
-\`\`\`ruby <!-- Только нужно будет убрать символы "\", оставив лишь "```ruby" -->
+<pre>
+<code class="highlight">&#x60;&#x60;&#x60;ruby
def foobar
- puts "Hello world!"
+ puts "Привет, мир!"
end
-\`\`\` <!-- И здесь тоже backslashes нужно убрать, т.е. оставить "```" -->
+&#x60;&#x60;&#x60;</code></pre>
-<-- Обратите внимание: фрагмент, указанный выше, не предваряется отступами,
-поскольку Github сам в состоянии определить границы блока - по строкам "```" -->
+Во фрагменте, приведённом выше, отступ не требуется.
+Кроме того, Github подсветит синтаксис языка, указанного после \`\`\`
-<!-- Горизонтальный разделитель (<hr />) -->
-<!-- Разделители добавляются вставкой строки из трёх и более
-(одинаковых) символов "*" или "-": -->
+## Горизонтальный разделитель
+Разделители (`<hr>`) добавляются вставкой строки из трёх и более
+(одинаковых) символов «*» или «-», с пробелами или без них:
+
+```markdown
***
---
-- - - <!-- между символами допустимы пробелы -->
+- - -
****************
+```
+
+## Ссылки
-<!-- Ссылки -->
-<!-- Одной из сильных сторон Markdown можно смело считать то,
+Одной из сильных сторон Markdown можно смело считать то,
как просто размечаются гиперссылки. Для создания ссылки укажите
текст ссылки, заключив его в квадратные скобки,
-и сразу после - url, заключенный в "круглые" -->
+и сразу после — URL-адрес, заключенный в круглые
+```markdown
[Ссылка!](http://test.com/)
+```
+Также для ссылки можно указать всплывающую подсказку (`title`), используя
+кавычки внутри круглых скобок:
-<!-- Также для ссылки можно указать всплывающую подсказку: -->
-
+```markdown
[Ссылка!](http://test.com/ "Ссылка на Test.com")
+```
+Относительные пути тоже возможны:
-<!-- В url можно использовать относительные пути: -->
-
+```markdown
[Перейти к музыке](/music/).
+```
-<!-- Markdown позволяет размечать ссылку в виде сноски: -->
+Markdown также позволяет размечать ссылку в виде сноски:
-[Здесь][link1] высможете узнать больше!
-А можно кликнуть [сюда][foobar], если очень хочется.
+<pre><code class="highlight">&#x5b;<span class="nv">Щёлкните эту ссылку</span>][<span class="ss">link1</span>] для подробной информации!
+&#x5b;<span class="nv">Также посмотрите эту ссылку,</span>][<span class="ss">foobar</span>] если хотите.
-<!-- где-нибудь внизу -->
-[link1]: http://test.com/ "Круто!"
-[foobar]: http://foobar.biz/ "Тоже хорошо!"
+&#x5b;<span class="nv">link1</span>]: <span class="sx">http://test.com/</span> <span class="nn">"Круто!"</span>
+&#x5b;<span class="nv">foobar</span>]: <span class="sx">http://foobar.biz/</span> <span class="nn">"Нормально!"</span></code></pre>
-<!-- Примечания:
-- Подсказка может быть заключена в одинарные кавычки вместо двойных,
- а также в круглые скобки.
-- Сноска может находиться в любом месте документа и может иметь
-идентификатор (далее ID) произвольной длины,
-лишь бы это ID был уникальным. -->
+`Title` также может быть в одинарных кавычках или круглых скобках, а также
+отсутствовать вовсе. Ссылки на сноски могут быть в любом месте документа,
+а идентификаторы могут быть какими угодно, лишь бы они были уникальными.
-<!-- Также при разметке ссылок-сносок можно опустить ID,
-если текст ссылки уникален в пределах документа: -->
+Существует также неявное именование, когда ссылка является идентификатором.
-Ссылка на [Google][].
+<pre><code class="highlight">&#x5b;<span class="nv">Это</span>][] ссылка.
-[google]: http://google.com/
+&#x5b;<span class="nv">это</span>]: <span class="sx">http://thisisalink.com/</span></code></pre>
-<!-- Правда, эта возможность не очень распространена. -->
+Правда, эта возможность не очень распространена.
-<!-- Изображения -->
-<!-- Разметка изображений очень похожа на разметку ссылок.
-Нужно всего лишь добавить "!" перед ссылкой! -->
+## Изображения
+Разметка изображений очень похожа на разметку ссылок.
+Нужно всего лишь добавить перед ссылкой восклицательный знак!
+```markdown
![Альтернативный текст для изображения](http://imgur.com/myimage.jpg "Подсказка")
+```
+Изображения тоже могут быть оформлены, как сноски.
-<!-- Изображения тоже могут быть оформлены, как сноски: -->
-
-![Альтернативный текст][myimage]
-
-![То же изображение ещё раз][myimage]
-
-[myimage]: relative/urls/cool/image.jpg "подсказка"
+<pre><code class="highlight">!&#x5b;<span class="nv">Это альтернативный текст.</span>][<span class="ss">myimage</span>]
-<!-- Ещё немного ссылок: -->
-<!-- Автоссылки -->
+&#x5b;<span class="nv">myimage</span>]: <span class="sx">relative/urls/cool/image.jpg</span> <span class="nn">"Если нужна подсказка, её можно добавить"</span></code></pre>
+## Разное
+### Автоссылки
+```markdown
Ссылка вида <http://testwebsite.com/> эквивалентна
[http://testwebsite.com/](http://testwebsite.com/)
+```
-<!-- Автоссылки для адресов электронной почты -->
+### Автоссылки для адресов электронной почты
+```markdown
<foo@bar.com>
+```
+
+### Экранирование символов
-<!-- Экранирование символов -->
+```markdown
+Я хочу напечатать *текст, заключённый в звёздочки*, но я не хочу,
+чтобы он был курсивным. Тогда я делаю так:
+\*Текст, заключённый в звёздочки\*
+```
-<!-- Может потребоваться вставить спецсимвол в текст "как есть",
-т.е. защитить его от обработки парсером.
-Такой символ должен быть "экранирован" с помощью обратной косой черты
-(символа "\"): -->
+### Клавиши на клавиатуре
+В Github Flavored Markdown для представления клавиш на клавиатуре
+вы можете использовать тег `<kbd>`.
-\*текст, заключённый в звёздочки!\*
+```markdown
+Ваш компьютер завис? Попробуйте нажать
+<kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd>
+```
-<!-- Таблицы -->
-<!-- Таблицы официально поддерживаются только в Github Flavored Markdown,
+### Таблицы
+Таблицы официально поддерживаются только в GitHub Flavored Markdown,
да и синтаксис имеют не слишком удобный.
-Но если очень нужно, размечайте таблицы так: -->
+Но если очень нужно, размечайте таблицы так:
+```markdown
| Столбец 1 | Столбец 2 | Столбец 3 |
| :----------- | :----------: | -----------: |
| Выравнивание | Выравнивание | Выравнивание |
| влево | по центру | вправо |
+```
+Или более компактно
-<!-- Или более компактно -->
-
-Колонка 1|Колонка 2|Колонка 3
+```markdown
+Столбец 1|Столбец 2|Столбец 3
:--|:-:|--:
Выглядит|это|страшновато...
-
-<!-- Ну вот и всё! -->
-
```
-За более подробной информацией обращайтесь к [статье](http://daringfireball.net/projects/markdown/syntax) Джона Грубера о синтаксисе Markdown.
+Ну вот и всё!
-Также часто бывает полезной отличная ["шпаргалка"](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) по Markdown от Adam Pritchard.
+За более подробной информацией обращайтесь к [статье](http://daringfireball.net/projects/markdown/syntax) Джона Грубера о синтаксисе Markdown.
-Если вдруг встретите ошибки в переводе или же захотите его дополнить, делайте pull requests - авторы всегда рады обратной связи!
+Также часто бывает полезной отличная ["шпаргалка"](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) по Markdown от Адама Притчарда.
diff --git a/ru-ru/nim-ru.html.markdown b/ru-ru/nim-ru.html.markdown
new file mode 100644
index 00000000..d05583d7
--- /dev/null
+++ b/ru-ru/nim-ru.html.markdown
@@ -0,0 +1,279 @@
+---
+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"]
+lang: ru-ru
+---
+
+Nim (ранее известный, как Nimrod) — язык программирования со статической
+типизацией, поддерживающий процедурный, объектно-ориентированный,
+функциональный и обобщённый стили программирования.
+
+Nim эффективный, выразительный и элегантный.
+
+```nim
+var # Объявление (и присваивание) переменных,
+ letter: char = 'n' # с указанием типа или без
+ lang = "N" & "im"
+ nLength : int = len(lang)
+ boat: float
+ truth: bool = false
+
+let # Используйте let *сразу* для объявления и связывания переменных.
+ legs = 400 # legs неизменяемый.
+ arms = 2_000 # Символ _ игнорируется и удобен для длинных чисел.
+ aboutPi = 3.15
+
+const # Константы вычисляются во время компиляции. Это обеспечивает
+ debug = true # производительность и полезно в выражениях этапа компиляции.
+ compileBadCode = false
+
+when compileBadCode: # `when` это `if` этапа компиляции.
+ legs = legs + 1 # Эта ошибка никогда не будет скомпилирована.
+ const input = readline(stdin) # Значения констант должны быть известны во
+ # время компиляции.
+
+discard 1 > 2 # Примечание. Компилятор будет жаловаться, если результат
+ # выражения не используется. `discard` обходит это.
+
+discard """
+Это может использоваться как многострочный комментарий.
+Или для не поддающегося синтаксическому анализу, сломанного кода
+"""
+
+#
+# Структуры данных
+#
+
+# Кортежи
+
+var
+ child: tuple[name: string, age: int] # Кортежи определяют *как* имя поля
+ today: tuple[sun: string, temp: float] # так *и* порядок полей.
+
+child = (name: "Rudiger", age: 2) # Присвоить все сразу литералом ()
+today.sun = "Overcast" # или отдельно по полям.
+today.temp = 70.1
+
+# Последовательности
+
+var
+ drinks: seq[string]
+
+drinks = @["Water", "Juice", "Chocolate"] # @[V1,..,Vn] является литералом
+ # последовательности
+
+drinks.add("Milk")
+
+if "Milk" in drinks:
+ echo "We have Milk and ", drinks.len - 1, " other drinks"
+
+let myDrink = drinks[2]
+
+#
+# Определение типов
+#
+
+# Определение собственных типов позволяет компилятору работать на вас.
+# Это то, что делает статическую типизацию мощной и полезной.
+
+type
+ Name = string # Псевдоним типа дает вам новый тип, который равнозначен
+ Age = int # старому типу, но более нагляден.
+ Person = tuple[name: Name, age: Age] # Определение структур данных.
+ AnotherSyntax = tuple
+ fieldOne: string
+ secondField: int
+
+var
+ john: Person = (name: "John B.", age: 17)
+ newage: int = 18 # Было бы лучше использовать Age, чем int
+
+john.age = newage # Но это все же работает, потому что int и Age синонимы.
+
+type
+ Cash = distinct int # `distinct` делает новый тип несовместимым с его
+ Desc = distinct string # базовым типом.
+
+var
+ money: Cash = 100.Cash # `.Cash` преобразует int в наш тип
+ description: Desc = "Interesting".Desc
+
+when compileBadCode:
+ john.age = money # Error! age is of type int and money is Cash
+ john.name = description # Компилятор говорит: "Нельзя!"
+
+#
+# Дополнительные типы и структуры данных
+#
+
+# Перечисления позволяют типу иметь одно из ограниченного числа значений
+
+type
+ Color = enum cRed, cBlue, cGreen
+ Direction = enum # Альтернативный формат
+ dNorth
+ dWest
+ dEast
+ dSouth
+var
+ orient = dNorth # `orient` имеет тип Direction, со значением `dNorth`
+ pixel = cGreen # `pixel` имеет тип Color, со значением `cGreen`
+
+discard dNorth > dEast # Перечисления обычно являются "порядковыми" типами
+
+# Поддиапазоны определяют ограниченный допустимый диапазон
+
+type
+ DieFaces = range[1..20] # Допустимым значением являются только int от 1 до 20
+var
+ my_roll: DieFaces = 13
+
+when compileBadCode:
+ my_roll = 23 # Error!
+
+# Arrays
+
+type
+ RollCounter = array[DieFaces, int] # Массивы фиксированной длины и
+ DirNames = array[Direction, string] # индексируются любым порядковым типом.
+ Truths = array[42..44, bool]
+var
+ counter: RollCounter
+ directions: DirNames
+ possible: Truths
+
+possible = [false, false, false] # Массивы создаются литералом [V1,..,Vn]
+possible[42] = true
+
+directions[dNorth] = "Ahh. The Great White North!"
+directions[dWest] = "No, don't go there."
+
+my_roll = 13
+counter[my_roll] += 1
+counter[my_roll] += 1
+
+var anotherArray = ["Default index", "starts at", "0"]
+
+# Доступны другие структуры данных, в том числе таблицы, множества,
+# списки, очереди и crit-bit деревья.
+# http://nim-lang.org/docs/lib.html#collections-and-algorithms (EN)
+
+#
+# IO и поток управления выполнением
+#
+
+# `case`, `readLine()`
+
+echo "Read any good books lately?"
+case readLine(stdin)
+of "no", "No":
+ echo "Go to your local library."
+of "yes", "Yes":
+ echo "Carry on, then."
+else:
+ echo "That's great; I assume."
+
+# `while`, `if`, `continue`, `break`
+
+import strutils as str # http://nim-lang.org/docs/strutils.html (EN)
+echo "I'm thinking of a number between 41 and 43. Guess which!"
+let number: int = 42
+var
+ raw_guess: string
+ guess: int
+while guess != number:
+ raw_guess = readLine(stdin)
+ if raw_guess == "": continue # Пропустить эту итерацию
+ guess = str.parseInt(raw_guess)
+ if guess == 1001:
+ echo("AAAAAAGGG!")
+ break
+ elif guess > number:
+ echo("Nope. Too high.")
+ elif guess < number:
+ echo(guess, " is too low")
+ else:
+ echo("Yeeeeeehaw!")
+
+#
+# Итерации (циклы)
+#
+
+for i, elem in ["Yes", "No", "Maybe so"]: # Или просто `for elem in`
+ echo(elem, " is at index: ", i)
+
+for k, v in items(@[(person: "You", power: 100), (person: "Me", power: 9000)]):
+ echo v
+
+let myString = """
+an <example>
+`string` to
+play with
+""" # Многострочная "сырая" строка
+
+for line in splitLines(myString):
+ echo(line)
+
+for i, c in myString: # Индекс и символ. Или `for j in` только для символов
+ if i mod 2 == 0: continue # Компактная форма `if`
+ elif c == 'X': break
+ else: echo(c)
+
+#
+# Процедуры
+#
+
+type Answer = enum aYes, aNo
+
+proc ask(question: string): Answer =
+ echo(question, " (y/n)")
+ while true:
+ case readLine(stdin)
+ of "y", "Y", "yes", "Yes":
+ return Answer.aYes # Перечисления могут быть квалифицированы
+ of "n", "N", "no", "No":
+ return Answer.aNo
+ else: echo("Please be clear: yes or no")
+
+proc addSugar(amount: int = 2) = # Значение поумолчанию 2, ничего не возвращает
+ assert(amount > 0 and amount < 9000, "Crazy Sugar")
+ for a in 1..amount:
+ echo(a, " sugar...")
+
+case ask("Would you like sugar in your tea?")
+of aYes:
+ addSugar(3)
+of aNo:
+ echo "Oh do take a little!"
+ addSugar()
+# Здесь нет необходимости в `else`. Возможны только `yes` и `no`.
+
+#
+# FFI (интерфейс внешних функций)
+#
+
+# Так как Nim компилируется в C, то FFI делается очень просто:
+
+proc strcmp(a, b: cstring): cint {.importc: "strcmp", nodecl.}
+
+let cmp = strcmp("C?", "Easy!")
+```
+
+Кроме того, 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 3246de82..3baa15f8 100644
--- a/ru-ru/objective-c-ru.html.markdown
+++ b/ru-ru/objective-c-ru.html.markdown
@@ -1,106 +1,171 @@
---
language: Objective-C
-filename: LearnObjectiveC.m
+filename: LearnObjectiveC-ru.m
contributors:
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
- ["Yannick Loriot", "https://github.com/YannickL"]
+ - ["Levi Bostian", "https://github.com/levibostian"]
translators:
- ["Evlogy Sutormin", "http://evlogii.com"]
+ - ["Dmitry Bessonov", "https://github.com/TheDmitry"]
lang: ru-ru
---
-Objective-C — компилируемый объектно-ориентированный язык программирования, используемый корпорацией Apple,
-построенный на основе языка Си и парадигм Smalltalk.
-В частности, объектная модель построена в стиле Smalltalk — то есть объектам посылаются сообщения.
+Objective-C — основной язык программирования, используемый корпорацией Apple
+для операционных систем OS X и iOS и их соответствующих фреймворках Cocoa и
+Cocoa Touch.
+Он является объектно-ориентированным языком программирования общего назначения,
+который добавляет обмен сообщениями в Smalltalk-стиле к языку программирования C.
-```objective_c
-// Однострочный комментарий
+```objective-c
+// Однострочные комментарии начинаются с //
/*
-Многострочный
-комментарий
+Так выглядят многострочные комментарии
*/
-// Импорт файлов фреймворка Foundation с помощью #import
+// Импорт заголовочных файлов фреймворка Foundation с помощью #import
+// Используйте <>, чтобы импортировать глобальные файлы (обычно фреймворки)
+// Используйте "", чтобы импортировать локальные файлы (из проекта)
#import <Foundation/Foundation.h>
#import "MyClass.h"
-// Точка входа в программу это функция main,
-// которая возвращает целый тип integer
+// Если вы включили модули для iOS >= 7.0 или OS X >= 10.9 проектов в
+// Xcode 5, вы можете импортировать фреймворки подобным образом:
+@import Foundation;
+
+// Точка входа в программу - это функция main,
+// которая возвращает целый тип
int main (int argc, const char * argv[])
{
- // Создание autorelease pool для управления памятью
+ // Создание autorelease pool для управления памятью в программе
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
+ // В место этого воспользуйтесь @autoreleasepool, если вы используете
+ // автоматический подсчет ссылок (ARC)
+ @autoreleasepool {
+
// Используйте NSLog для печати в консоль
- NSLog(@"Hello World!"); // Напечатает строку "Hello World!"
+ NSLog(@"Привет Мир!"); // Напечатает строку "Привет Мир!"
///////////////////////////////////////
// Типы и переменные
///////////////////////////////////////
- // Простое объявление
+ // Объявление простых типов
int myPrimitive1 = 1;
long myPrimitive2 = 234554664565;
+ // Объявление объектов
// Помещайте * в начало названия объекта для строго типизированного объявления
MyClass *myObject1 = nil; // Строгая типизация
id myObject2 = nil; // Слабая типизация
-
- NSLog(@"%@ and %@", myObject1, [myObject2 description]); // напечатает "(null) and (null)"
// %@ – это объект
- // 'description' это общий для всех объектов метод вывода данных
+ // 'description' - это общий для всех объектов метод вывода данных
+ NSLog(@"%@ and %@", myObject1, [myObject2 description]); // напечатает "(null) and (null)"
// Строка
- NSString *worldString = @"World";
- NSLog(@"Hello %@!", worldString); // напечатает "Hello World!"
+ NSString *worldString = @"Мир";
+ NSLog(@"Привет %@!", worldString); // напечатает "Привет Мир!"
+ // NSMutableString - это изменяемая версия NSString-объекта
+ NSMutableString *mutableString = [NSMutableString stringWithString:@"Привет"];
+ [mutableString appendString:@" Мир!"];
+ NSLog(@"%@", mutableString); // напечатает => "Привет Мир!"
// Символьные литералы
NSNumber *theLetterZNumber = @'Z';
- char theLetterZ = [theLetterZNumber charValue];
+ char theLetterZ = [theLetterZNumber charValue]; // или 'Z'
NSLog(@"%c", theLetterZ);
- // Целочисленный литералы
+ // Целочисленные литералы
NSNumber *fortyTwoNumber = @42;
- int fortyTwo = [fortyTwoNumber intValue];
+ int fortyTwo = [fortyTwoNumber intValue]; // или '42'
NSLog(@"%i", fortyTwo);
// Беззнаковый целочисленный литерал
NSNumber *fortyTwoUnsignedNumber = @42U;
- unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue];
+ unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; // или 42
NSLog(@"%u", fortyTwoUnsigned);
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
- short fortyTwoShort = [fortyTwoShortNumber shortValue];
+ short fortyTwoShort = [fortyTwoShortNumber shortValue]; // или 42
NSLog(@"%hi", fortyTwoShort);
+ NSNumber *fortyOneShortNumber = [NSNumber numberWithShort:41];
+ unsigned short fortyOneUnsigned = [fortyOneShortNumber unsignedShortValue]; // или 41
+ NSLog(@"%u", fortyOneUnsigned);
+
NSNumber *fortyTwoLongNumber = @42L;
- long fortyTwoLong = [fortyTwoLongNumber longValue];
+ long fortyTwoLong = [fortyTwoLongNumber longValue]; // или 42
NSLog(@"%li", fortyTwoLong);
+
+ NSNumber *fiftyThreeLongNumber = @53L;
+ unsigned long fiftyThreeUnsigned = [fiftyThreeLongNumber unsignedLongValue]; // или 53
+ NSLog(@"%lu", fiftyThreeUnsigned);
// Вещественный литерал
NSNumber *piFloatNumber = @3.141592654F;
- float piFloat = [piFloatNumber floatValue];
- NSLog(@"%f", piFloat);
+ float piFloat = [piFloatNumber floatValue]; // или 3.141592654f
+ NSLog(@"%f", piFloat); // напечатает 3.141592654
+ NSLog(@"%5.2f", piFloat); // напечатает " 3.14"
NSNumber *piDoubleNumber = @3.1415926535;
- double piDouble = [piDoubleNumber doubleValue];
+ double piDouble = [piDoubleNumber doubleValue]; // или 3.1415926535
NSLog(@"%f", piDouble);
-
+ NSLog(@"%4.2f", piDouble); // напечатает "3.14"
+
+ // NSDecimalNumber - это класс с фиксированной точкой, который является
+ // более точным, чем float или double
+ NSDecimalNumber *oneDecNum = [NSDecimalNumber decimalNumberWithString:@"10.99"];
+ NSDecimalNumber *twoDecNum = [NSDecimalNumber decimalNumberWithString:@"5.002"];
+ // NSDecimalNumber не способен использовать стандартные +, -, *, / операторы,
+ // поэтому он предоставляет свои собственные:
+ [oneDecNum decimalNumberByAdding:twoDecNum];
+ [oneDecNum decimalNumberBySubtracting:twoDecNum];
+ [oneDecNum decimalNumberByMultiplyingBy:twoDecNum];
+ [oneDecNum decimalNumberByDividingBy:twoDecNum];
+ NSLog(@"%@", oneDecNum); // напечатает "10.99", т.к. NSDecimalNumber - изменяемый
+
// BOOL (булевый) литерал
NSNumber *yesNumber = @YES;
NSNumber *noNumber = @NO;
-
+ // или
+ BOOL yesBool = YES;
+ BOOL noBool = NO;
+ NSLog(@"%i", yesBool); // напечатает 1
+
// Массив
+ // Может содержать различные типы данных, но должен быть объектом Objective-C
NSArray *anArray = @[@1, @2, @3, @4];
NSNumber *thirdNumber = anArray[2];
- NSLog(@"Third number = %@", thirdNumber); // Print "Third number = 3"
+ NSLog(@"Третье число = %@", thirdNumber); // Напечатает "Третье число = 3"
+ // NSMutableArray - это изменяемая версия NSArray, допускающая вам изменять
+ // элементы в массиве и расширять или сокращать массив.
+ // Удобный, но не эффективный как NSArray.
+ NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:2];
+ [mutableArray addObject:@"Привет"];
+ [mutableArray addObject:@"Мир"];
+ [mutableArray removeObjectAtIndex:0];
+ NSLog(@"%@", [mutableArray objectAtIndex:0]); // напечатает "Мир"
// Словарь
- NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
- NSObject *valueObject = aDictionary[@"A Key"];
- NSLog(@"Object = %@", valueObject); // Напечатает "Object = (null)"
-
+ NSDictionary *aDictionary = @{ @"ключ1" : @"значение1", @"ключ2" : @"значение2" };
+ NSObject *valueObject = aDictionary[@"Ключ"];
+ NSLog(@"Объект = %@", valueObject); // Напечатает "Объект = (null)"
+ // NSMutableDictionary тоже доступен, как изменяемый словарь
+ NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:2];
+ [mutableDictionary setObject:@"значение1" forKey:@"ключ1"];
+ [mutableDictionary setObject:@"значение2" forKey:@"ключ2"];
+ [mutableDictionary removeObjectForKey:@"ключ1"];
+
+ // Множество
+ NSSet *set = [NSSet setWithObjects:@"Привет", @"Привет", @"Мир", nil];
+ NSLog(@"%@", set); // напечатает {(Hello, World)} (порядок может отличаться)
+ // NSMutableSet тоже доступен, как изменяемое множество
+ NSMutableSet *mutableSet = [NSMutableSet setWithCapacity:2];
+ [mutableSet addObject:@"Привет"];
+ [mutableSet addObject:@"Привет"];
+ NSLog(@"%@", mutableSet); // напечатает => {(Привет)}
+
///////////////////////////////////////
// Операторы
///////////////////////////////////////
@@ -124,13 +189,13 @@ int main (int argc, const char * argv[])
// Условный оператор
if (NO)
{
- NSLog(@"I am never run");
+ NSLog(@"Я никогда не выполнюсь");
} else if (0)
{
- NSLog(@"I am also never run");
+ NSLog(@"Я тоже никогда не выполнюсь");
} else
{
- NSLog(@"I print");
+ NSLog(@"Я напечатаюсь");
}
// Ветвление с множественным выбором
@@ -138,15 +203,15 @@ int main (int argc, const char * argv[])
{
case 0:
{
- NSLog(@"I am never run");
+ NSLog(@"Я никогда не выполнюсь");
} break;
case 1:
{
- NSLog(@"I am also never run");
+ NSLog(@"Я тоже никогда не выполнюсь");
} break;
default:
{
- NSLog(@"I print");
+ NSLog(@"Я напечатаюсь");
} break;
}
@@ -170,7 +235,7 @@ int main (int argc, const char * argv[])
// "2,"
// "3,"
- // // Цикл просмотра
+ // Цикл просмотра
NSArray *values = @[@0, @1, @2, @3];
for (NSNumber *value in values)
{
@@ -180,20 +245,32 @@ int main (int argc, const char * argv[])
// "2,"
// "3,"
+ // Цикл for для объектов. Может использоваться с любым объектом Objective-C
+ for (id item in values) {
+ NSLog(@"%@,", item);
+ } // напечатает => "0,"
+ // "1,"
+ // "2,"
+ // "3,"
+
// Обработка исключений
@try
{
// Ваше исключение здесь
@throw [NSException exceptionWithName:@"FileNotFoundException"
- reason:@"File Not Found on System" userInfo:nil];
+ reason:@"Файл не найден в системе" userInfo:nil];
} @catch (NSException * e)
{
- NSLog(@"Exception: %@", e);
+ NSLog(@"Исключение: %@", e);
} @finally
{
- NSLog(@"Finally");
- } // => напечатает "Exception: File Not Found on System"
- // "Finally"
+ NSLog(@"В конце отводится время для очистки.");
+ } // => напечатает "Исключение: Файл не найден в системе"
+ // "В конце отводится время для очистки."
+
+ // NSError - это полезные объекты для аргументов функции, чтобы заполнить их
+ // пользовательскими ошибками.
+ NSError *error = [NSError errorWithDomain:@"Неправильный эл. адрес." code:4 userInfo:nil];
///////////////////////////////////////
// Объекты
@@ -203,13 +280,16 @@ int main (int argc, const char * argv[])
// Объект не является полнофункциональным пока обе части не выполнятся.
MyClass *myObject = [[MyClass alloc] init];
- // В Objective-C можель ООП базируется на передаче сообщений.
+ // В Objective-C модель ООП базируется на передаче сообщений.
// В Objective-C Вы не просто вызваете метод; вы посылаете сообщение.
- [myObject instanceMethodWithParameter:@"Steve Jobs"];
+ [myObject instanceMethodWithParameter:@"Стив Джобс"];
// Очищайте память, перед завершением работы программы.
[pool drain];
+ // Конец @autoreleasepool
+ }
+
// Конец программы.
return 0;
}
@@ -222,63 +302,145 @@ int main (int argc, const char * argv[])
// Синтаксис объявления:
// @interface ИмяКласса : ИмяКлассаРодителя <ИмплементируемыеПротоколы>
// {
-// Объявление переменных;
+// тип имя; <= Объявление переменных;
// }
+// @property тип имя; <= объявление свойств
// -/+ (тип) Объявление метода(ов).
// @end
-
-
-@interface MyClass : NSObject <MyProtocol>
+@interface MyClass : NSObject <MyProtocol> // NSObject - это базовый класс в Objective-C.
{
- int count;
- id data;
+ // Объявления экземпляров переменных (может существовать в файлах интерфейса или реализвации)
+ int count; // По умолчанию защищенный доступ.
+ @private id data; // Приватный доступ (Намного удобнее объявлять в файле реализации)
NSString *name;
}
-// При объявлении свойств сразу генерируются геттер и сеттер
-@property int count;
-@property (copy) NSString *name; // Скопировать объект в ходе присвоения.
-@property (readonly) id data; // Генерация только геттера
+// Удобное обозначение для переменных с открытым (public) доступом
+// автоматически генерируется сеттер-метод
+// По умолчанию название сеттер-метода начинается с 'set' с последующим именем
+// переменной из @property
+@property int propInt; // Имя сеттер-метода = 'setPropInt'
+@property (copy) id copyId; // (copy) => Скопировать объект в ходе присвоения.
+// (readonly) => Не позволяет установить значение вне @interface
+@property (readonly) NSString *roString; // Используйте @synthesize
+ // в @implementation, чтобы создать аксессор
+// Вы можете настроить геттер и сеттер имена вместо используемого 'set'-имени по умолчанию:
+@property (getter=lengthGet, setter=lengthSet:) int length;
// Методы
-+/- (return type)methodSignature:(Parameter Type *)parameterName;
++/- (возвращаемый тип)сигнатураМетода:(Параметр типа *)имяПараметра;
// + для методов класса
+ (NSString *)classMethod;
++ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight;
-// - для метода объекта
+// - для методов объекта
- (NSString *)instanceMethodWithParameter:(NSString *)string;
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
-@end
+// Методы-конструктор с аргументом:
+- (id)initWithDistance:(int)defaultDistance;
+// В Objective-C имена методов очень описательные. Всегда имена методов соответствуют своим аргументам
+
+@end // Устанавливает конец интерфейса (interface)
+
+
+// Чтобы обратиться к открытым (public) переменным из файла реализации, @property генерирует сеттер-метод
+// автоматически. Название метода - это 'set' с последующим именем переменной из @property:
+MyClass *myClass = [[MyClass alloc] init]; // создает экземпляр объекта класса MyClass
+[myClass setCount:10];
+NSLog(@"%d", [myClass count]); // напечатает => 10
+// Или используйте свой геттер и сеттер методы, которые определены в @interface:
+[myClass lengthSet:32];
+NSLog(@"%i", [myClass lengthGet]); // напечатает => 32
+// Для удобства вы можете использовать точечную нотацию,
+// чтобы установить и получить доступ к переменным объекта:
+myClass.count = 45;
+NSLog(@"%i", myClass.count); // напечатает => 45
+
+// Вызов методов класса:
+NSString *classMethodString = [MyClass classMethod];
+MyClass *classFromName = [MyClass myClassFromName:@"Привет"];
+
+// Вызов методов экземпляра:
+MyClass *myClass = [[MyClass alloc] init]; // Создает экземпляр объекта MyClass
+NSString *stringFromInstanceMethod = [myClass instanceMethodWithParameter:@"Привет"];
+
+// Селекторы
+// Это способ динамически представить методы. Используйте для вызова методов класса, передайте методы
+// через функции, чтобы сказать другим классам, что они должны вызвать их и сохранить методы
+// как переменные
+// SEL - это тип данных. @selector() вернет селектор из предоставленного имени метода
+// methodAParameterAsString:andAParameterAsNumber: - это название метода в MyClass
+SEL selectorVar = @selector(methodAParameterAsString:andAParameterAsNumber:);
+if ([myClass respondsToSelector:selectorVar]) { // Проверяет содержит ли класс метод
+ // Необходимо установить все аргументы метода в один объект, что отправить его в performSelector-функцию
+ NSArray *arguments = [NSArray arrayWithObjects:@"Привет", @4, nil];
+ [myClass performSelector:selectorVar withObject:arguments]; // Вызывает метод
+} else {
+ // NSStringFromSelector() вернет NSString название метода полученного селектором
+ NSLog(@"MyClass не содержит метод: %@", NSStringFromSelector(selectedVar));
+}
+
+// Имплементируйте методы в файле MyClass.m:
+@implementation MyClass {
+ long distance; // Переменная экземпляра с закрытым (private) доступом
+ NSNumber height;
+}
-// Имплементируйте методы в файле МойКласс.m:
+// Для доступа к public переменной, объявленной в интерфейсе, используйте '_' перед названием переменной:
+_count = 5; // Ссылается на "int count" из интерфейса MyClass
+// Получение доступа к переменной, объявленной в реализации происходит следующим образом:
+distance = 18; // Ссылается на "long distance" из реализации MyClass
+// Для использования в иплементации переменной, объявленной в интерфейсе с помощью @property,
+// следует использовать @synthesize для создания переменной аксессора:
+@synthesize roString = _roString; // Теперь _roString доступна в @implementation (реализации интерфейса)
-@implementation MyClass
+// Вызывается в первую очередь, перед вызовом других медотов класса или инициализации других объектов
++ (void)initialize
+{
+ if (self == [MyClass class]) {
+ distance = 0;
+ }
+}
// Вызывается при высвобождении памяти под объектом
- (void)dealloc
{
+ [height release]; // Если не используется ARC, убедитесь в освобождении переменных объекта класса
+ [super dealloc]; // and call parent class dealloc
}
-// Конструкторы – это способ осздания объектов класса.
-// Это обычный конструктор вызываемый при создании объекта клсааа.
+// Конструкторы – это способ создания объектов класса.
+// Это конструктор по умолчанию, который вызывается, когда объект инициализируется.
- (id)init
{
- if ((self = [super init]))
+ if ((self = [super init])) // 'super' используется для того, чтобы обратиться к методам родительского класса
{
- self.count = 1;
+ self.count = 1; // 'self' используется для вызова самого себя
}
return self;
}
+// Можно создать конструкторы, которые содержат аргументы:
+- (id)initWithDistance:(int)defaultDistance
+{
+ distance = defaultDistance;
+ return self;
+}
+ (NSString *)classMethod
{
return [[self alloc] init];
}
++ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight
+{
+ height = defaultHeight;
+ return [[self alloc] init];
+}
+
- (NSString *)instanceMethodWithParameter:(NSString *)string
{
- return @"New string";
+ return @"Новая строка";
}
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
@@ -286,23 +448,364 @@ int main (int argc, const char * argv[])
return @42;
}
+// Objective-C не содержит объявление приватных методов, но вы можете имитировать их.
+// Чтобы сымитировать приватный метод, создайте метод в @implementation, но не в @interface.
+- (NSNumber *)secretPrivateMethod {
+ return @72;
+}
+[self secretPrivateMethod]; // Вызывает приватный метод
+
// Методы объявленные в МyProtocol (см. далее)
- (void)myProtocolMethod
{
- // имплементация
+ // операторы
}
+@end // Устанавливает конец реализации (implementation)
+
+///////////////////////////////////////
+// Категории
+///////////////////////////////////////
+// Категория - это группа методов предназначенные для того, чтобы расширить класс. Они позволяют вам добавить новые методы
+// к существующему классу для организационных целей. Это не стоит путать с подклассами.
+// Подклассы предназначены для ИЗМЕНЕНИЯ функциональности объекта пока как категории ДОБАВЛЯЮТ
+// функциональность в объект.
+// Категории позволяют вам:
+// -- Добавлять методы в существующий класс для организационных целей.
+// -- Допускает вам расширять объекты Objective-C классов (напр.: NSString) добавить ваши собственные методы.
+// -- Добавляет возможность создать защищенные и закрытые методы классов.
+// ПРИМЕЧАНИЕ: Не переопределяйте методы базового класса в категории даже если у вас есть возможность это сделать
+// to. Переопределение методов может привести к ошибкам компиляции позднее между различными категориями и это
+// нарушает цель категорий, чтобы добавлять только функциональность. Вместо этого подклассы переопределяют методы.
+
+// Здесь простой базовый класс Car.
+@interface Car : NSObject
+
+@property NSString *make;
+@property NSString *color;
+
+- (void)turnOn;
+- (void)accelerate;
+
@end
-/*
- * Протокол объявляет методы которые должны быть имплементированы
- * Протокол не является классом. Он просто определяет интерфейс,
- * который должен быть имплементирован.
- */
+// И реализация базового класса Car:
+#import "Car.h"
+
+@implementation Car
+
+@synthesize make = _make;
+@synthesize color = _color;
+
+- (void)turnOn {
+ NSLog(@"Машина заведена.");
+}
+- (void)accelerate {
+ NSLog(@"Ускорение.");
+}
-@protocol MyProtocol
- - (void)myProtocolMethod;
@end
+
+// Теперь, если мы хотим создать объект Truck - грузовик, мы должны создать подкласс класса Car, что
+// изменит функционал Car и позволит вести себя подобно грузовику. Но что, если мы хотим только добавить
+// определенный функционал в уже существующий класс Car? Например - чистка автомобиля. Мы просто создадим
+// категорию, которая добавит несколько методов для чистки автомобиля в класс Car:
+// @interface ИмяФайла: Car+Clean.h (ИмяБазовогоКласса+ИмяКатегории.h)
+#import "Car.h" // Убедитесь в том, что базовый класс импортирован для расширения.
+
+@interface Car (Clean) // Имя категории внутри (), следующие после имени базового класса.
+
+- (void)washWindows; // Названия новых методов, которые мы добавляем в наш объект Car.
+- (void)wax;
+
+@end
+
+// @implementation имя файла: Car+Clean.m (ИмяБазовогоКласса+ИмяКатегории.m)
+#import "Car+Clean.h" // Импортируйте Очистку файл @interface категории.
+
+@implementation Car (Clean)
+
+- (void)washWindows {
+ NSLog(@"Окна промыли.");
+}
+- (void)wax {
+ NSLog(@"Воском натерли.");
+}
+
+@end
+
+// Любой экземпляр объекта Car имеет возможность воспользоваться категорией. Все, что нужно сделать, это импортировать ее:
+#import "Car+Clean.h" // Импортировать как множество различных категорий, как вы хотите использовать.
+#import "Car.h" // Кроме того, необходимо импортировать базовый класс для использования его оригинальные функциональные возможности.
+
+int main (int argc, const char * argv[]) {
+ @autoreleasepool {
+ Car *mustang = [[Car alloc] init];
+ mustang.color = @"Красный";
+ mustang.make = @"Форд";
+
+ [mustang turnOn]; // Используйте методы из базового класса Car.
+ [mustang washWindows]; // Используйте методы категории Clean из класса Car.
+ }
+ return 0;
+}
+
+// Objective-C не поддерживает объявление защищенных методов, но вы можете имитировать их.
+// Создайте категорию, содержащую все защищенные методы, затем импортируйте ее только в
+// @implementation-файле класса, относящегося к классу Car:
+@interface Car (Protected) // Наименование категории с помощью 'Protected'
+// дает знать, что методы защищенные.
+
+- (void)lockCar; // Здесь перечисляются методы, которые должны быть созданы
+// только с помощью объектов класса Car.
+
+@end
+// Чтобы воспользоваться защищенными методами, импортируйте категорию, затем реализуйте методы:
+#import "Car+Protected.h" // Запомните, делайте импорт только в файле с @implementation.
+
+@implementation Car
+
+- (void)lockCar {
+ NSLog(@"Машина закрыта."); // Экземпляры класса Car не могут использовать
+// метод lockCar, потому что он объявлен не в @interface.
+}
+
+@end
+
+///////////////////////////////////////
+// Расширения
+///////////////////////////////////////
+// Расширения позволяют вам переопределять атрибуты свойств и методов
+// с открытым доступом в @interface.
+// @interface имя файла: Shape.h
+@interface Shape : NSObject // Расширение базового класса Shape переопределяет
+ // свои поля ниже.
+
+@property (readonly) NSNumber *numOfSides;
+
+- (int)getNumOfSides;
+
+@end
+// Вы можете переопределить numOfSides-переменную или getNumOfSides-метод
+// Внесение изменений с помощью расширения делается следующим образом:
+// @implementation имя файла: Shape.m
+#import "Shape.h"
+// Расширения "живут" в том же файле, где и @implementation класса.
+@interface Shape () // После имени базового класса скобки () объявляют расширение.
+
+@property (copy) NSNumber *numOfSides; // Делает numOfSides-свойство
+ // копирующим (copy) вместо свойства только для чтения (readonly).
+-(NSNumber)getNumOfSides; // Изменяет метод getNumOfSides так,
+ // чтобы он возвращал объект NSNumber вместо типа int.
+-(void)privateMethod; // Вы также можете создать новый закрытый метод
+ // внутри расширения.
+
+@end
+// Главный @implementation:
+@implementation Shape
+
+@synthesize numOfSides = _numOfSides;
+
+-(NSNumber)getNumOfSides { // Все операторы внутри расширения
+ // должны быть в @implementation.
+ return _numOfSides;
+}
+-(void)privateMethod {
+ NSLog(@"Закрытый метод созданный с помощью расширения.");
+ NSLog(@"Экземпляр Shape не может вызвать этот метод.");
+}
+
+@end
+
+///////////////////////////////////////
+// Протоколы
+///////////////////////////////////////
+// Протокол объявляет методы, которые могут быть реализованы с помощью
+// любого класса. Протоколы сами по себе не являются классами. Они просто
+// определяют интерфейс, который должен быть реализован другими объектами.
+// @protocol имя файла: "CarUtilities.h"
+@protocol CarUtilities <NSObject> // <NSObject> => Имя другого протокола,
+// который включен в этот протокол.
+ @property BOOL engineOn; // Адаптирующий класс должен определить
+// все @synthesize для @property и
+ - (void)turnOnEngine; // определить все методы.
+@end
+// Ниже пример класса, реализующий протокол.
+#import "CarUtilities.h" // Импорт файла с @protocol.
+
+@interface Car : NSObject <CarUtilities> // Внутри <> имя протокола
+// Здесь вам не нужно указывать @property или имена методов для CarUtilities.
+// Они нужны только для @implementation.
+- (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // Вы также можете
+// указать тип протоколов.
+@end
+// В @implementation нужно реализовать все @property и методы для протокола.
+@implementation Car : NSObject <CarUtilities>
+
+@synthesize engineOn = _engineOn; // Создайте @synthesize-оператор
+// для "@property engineOn".
+
+- (void)turnOnEngine { // Реализуйте turnOnEngine как вам угодно. Протоколы
+// не определят,
+ _engineOn = YES; // как вам реализовать метод, он только требует,
+// чтобы вы реализовали его.
+}
+// Вы можете использовать протокол как данные, если вы знаете, что он реализует
+// методы и переменные.
+- (void)turnOnEngineWithCarUtilities:(id <CarUtilities>)objectOfSomeKind {
+ [objectOfSomeKind engineOn]; // У вас есть доступ к переменным объекта
+ [objectOfSomeKind turnOnEngine]; // и методам.
+ [objectOfSomeKind engineOn]; // Может или не может быть значение YES. Класс
+// реализует как нужно.
+}
+
+@end
+// Экземпляры класса Car сейчас имеют доступ к протоколу.
+Car *carInstance = [[Car alloc] init];
+[carInstance setEngineOn:NO];
+[carInstance turnOnEngine];
+if ([carInstance engineOn]) {
+ NSLog(@"Двигатель запущен."); // напечатает => "Двигатель запущен."
+}
+// Убедитись в том, что объект типа 'id' реализует протокол перед вызовом методов протокола:
+if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {
+ NSLog(@"Не работает, т.к. класс MyClass не реализует протокол CarUtilities.");
+} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) {
+ NSLog(@"Работает как класс Car, который реализует протокол CarUtilities.");
+}
+// Категории тоже могут реализовать протоколы:
+// @interface Car (CarCategory) <CarUtilities>
+// Вы можете реализовать много протоколов:
+// @interface Car : NSObject <CarUtilities, CarCleaning>
+// ЗАМЕЧАНИЕ: Если два или более протоколов полагаются друг на друга,
+// убедитесь, что они ранее объявлены:
+#import "Brother.h"
+
+@protocol Brother; // Оператор раннего объявления. Без него компилятор
+// выдаст ошибку.
+
+@protocol Sister <NSObject>
+
+- (void)beNiceToBrother:(id <Brother>)brother;
+
+@end
+
+// Рассмотрите проблему, где протокол Sister полагается на протокол Brother,
+// а Brother полагается на Sister.
+#import "Sister.h"
+
+@protocol Sister; // Эти строки предотвращают рекурсию, решая этим проблему.
+
+@protocol Brother <NSObject>
+
+- (void)beNiceToSister:(id <Sister>)sister;
+
+@end
+
+
+///////////////////////////////////////
+// Блоки
+///////////////////////////////////////
+// Блоки - это операторы кода, наподобие функции, которую возможно использовать
+// как данные.
+// Ниже простой блок с целочисленным аргументом, и возвращает аргумент плюс 4.
+int (^addUp)(int n); // Объявите переменную, чтобы сохранить блок.
+void (^noParameterBlockVar)(void); // Пример объявления блока-переменной
+// без аргументов.
+// Блоки имею доступ к переменным в той же области видимости. Но переменные
+// будут только для чтения, и значения переданных в блок станут значением
+// переменной, когда блок создастся.
+int outsideVar = 17; // Если мы редактируем outsideVar после объявления addUp,
+// outsideVar остается равным 17.
+__block long mutableVar = 3; // __block делают переменные перезаписываемыми
+// в блоках, в отличие от outsideVar.
+addUp = ^(int n) { // Удалите (int n) в блоке, чтобы не принимать
+// какие-либо параметры.
+ NSLog(@"Вы можете иметь столько строк в блоке, сколько вы хотели.");
+ NSSet *blockSet; // Также вы можете объявить локальные переменные.
+ mutableVar = 32; // Присвоить новое значение к __block-переменной.
+ return n + outsideVar; // Необязательный оператор возврата.
+}
+int addUp = add(10 + 16); // Вызывает блок кода с аргументами.
+// Блоки часто используются как аргументы функции, чтобы позже их вызвать, или
+// как функции обратного вызова (callbacks).
+@implementation BlockExample : NSObject
+
+- (void)runBlock:(void (^)(NSString))block {
+ NSLog(@"В аргументе блок ничего не возвращает и принимает NSString-объект.");
+ block(@"Аргумент передан блоку на исполнение."); // Вызов блока.
+}
+
+@end
+
+
+///////////////////////////////////////
+// Управление памятью
+///////////////////////////////////////
+/*
+Для каждого объекта, используемого в приложении, должна быть выделена память
+для таких объектов. Когда приложение прекращает использование объекта, память
+должна быть освобождена, чтобы гарантировать эффективность приложения.
+Objective-C не использует сборщик мусора, а вместо этого применяет подсчет ссылок.
+Пока существует по крайней мере одна ссылка на объект (также называется
+"владение" объектом), то объект будет доступен к использованию (еще известно
+как "право владения").
+
+Когда экземпляр владеет объектом, его ссылка увеличивается на один. Когда
+объекта освобождается, счетчик ссылки уменьшается на один. Когда счетчик ссылки
+равен нулю, объект удаляется из памяти.
+
+Над всеми объектами взаимодействуют, следуя паттерну:
+(1) создание объекта, (2) использование объекта, (3) затем освобождение объекта из памяти.
+*/
+
+MyClass *classVar = [MyClass alloc]; // 'alloc' устанавливает счетчик ссылки
+// объекта classVar на 1 и возвращает указатель на объект.
+[classVar release]; // Уменьшает счетчик ссылки объекта classVar
+// 'retain' заявляет право собственности на существующий экземпляр объекта
+// и увеличивает счетчик ссылки. Затем вернет указатель на объект.
+MyClass *newVar = [classVar retain]; // Если classVar освободится, объект
+// останется в памяти, потому что newVar - владелец
+[classVar autorelease]; // Удалит право на владение объектом
+// в конце @autoreleasepool блока. Вернет указатель на объект.
+
+// @property может использовать 'retain' и 'assign' тоже для маленького
+// удобного определения
+@property (retain) MyClass *instance; // Освободит старое значение и сохранит
+// одно новое (строгая ссылка)
+@property (assign) NSSet *set; // Укажет на новое значение
+// без сохранения/освобождения старого значения (слабая ссылка)
+
+// Автоматический подсчет ссылок (ARC)
+// Управление памятью может быть трудным, поэтому в Xcode 4.2 и iOS 4 введен
+// автоматический подсчет ссылок (ARC).
+// ARC - это особенность компилятора, который помещает "retain", "release"
+// и "autorelease" автоматически за вас тогда, когда используется ARC,
+// вам не нужно больше обращаться к "retain", "release" или "autorelease"
+MyClass *arcMyClass = [[MyClass alloc] init];
+// ... код, использующий объект arcMyClass
+// Без ARC, вам нужно было бы вызвать: [arcMyClass release] после того, как вы
+// завершите работу с объектом arcMyClass. Но с ARC,
+// теперь этого не нужно делать. Он будет помещать release-вызов за вас
+
+// Что касается 'assign' и 'retain' @property атрибутов, в ARC вы должны
+// использовать 'weak' и 'strong'
+@property (weak) MyClass *weakVar; // 'weak' не принимает право на владение
+// объектом. Если исходный счетчик ссылки экземпляра обнуляется,
+// weakVar-свойство автоматически примет значение nil,
+// во избежание падения приложения
+@property (strong) MyClass *strongVar; // 'strong' принимает право на владение
+// объектом. Гарантирует, что объект останется в памяти для использования
+
+// Для обычных переменных (не объявленных с помощью @property), используйте
+// следующий способ:
+__strong NSString *strongString; // По умолчанию. Переменная сохраняется в памяти,
+// пока она не покинет область видимости
+__weak NSSet *weakSet; // Слабая ссылка на существующий объект. Когда существующий
+// объект освобождается, weakSet принимает nil
+__unsafe_unretained NSArray *unsafeArray; // Похож на __weak, но unsafeArray
+// не принимает nil, когда существующий объект освобождается
+
```
## На почитать
diff --git a/ru-ru/paren-ru.html.markdown b/ru-ru/paren-ru.html.markdown
new file mode 100644
index 00000000..9b801e46
--- /dev/null
+++ b/ru-ru/paren-ru.html.markdown
@@ -0,0 +1,196 @@
+---
+language: Paren
+filename: learnparen-ru.paren
+contributors:
+ - ["KIM Taegyoon", "https://github.com/kimtg"]
+translators:
+ - ["Dmitry Bessonov", "https://github.com/TheDmitry"]
+lang: ru-ru
+---
+
+[Paren](https://bitbucket.org/ktg/paren) - это диалект языка Лисп. Он спроектирован как встроенный язык.
+
+Примеры взяты <http://learnxinyminutes.com/docs/racket/>.
+
+```scheme
+;;; Комментарии
+# комментарии
+
+;; Однострочные комментарии начинаются с точки с запятой или символа решетки
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 1. Примитивные типы данных и операторы
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Числа
+123 ; int
+3.14 ; double
+6.02e+23 ; double
+(int 3.14) ; => 3 : int
+(double 123) ; => 123 : double
+
+;; Обращение к функции записывается так: (f x y z ...),
+;; где f - функция, а x, y, z, ... - операнды
+;; Если вы хотите создать буквальный список данных, используйте (quote), чтобы
+;; предотвратить ненужные вычисления
+(quote (+ 1 2)) ; => (+ 1 2)
+;; Итак, некоторые арифметические операции
+(+ 1 1) ; => 2
+(- 8 1) ; => 7
+(* 10 2) ; => 20
+(^ 2 3) ; => 8
+(/ 5 2) ; => 2
+(% 5 2) ; => 1
+(/ 5.0 2) ; => 2.5
+
+;;; Логический тип
+true ; обозначает истину
+false ; обозначает ложь
+(! true) ; => false
+(&& true false (prn "досюда не доходим")) ; => false
+(|| false true (prn "досюда не доходим")) ; => true
+
+;;; Символы - это числа (int).
+(char-at "A" 0) ; => 65
+(chr 65) ; => "A"
+
+;;; Строки - это массив символов с фиксированной длиной.
+"Привет, мир!"
+"Benjamin \"Bugsy\" Siegel" ; обратная косая черта экранирует символ
+"Foo\tbar\r\n" ; включает управляющие символы в стиле Cи: \t \r \n
+
+;; Строки тоже могут объединяться!
+(strcat "Привет " "мир!") ; => "Привет мир!"
+
+;; Строка может трактоваться подобно списку символов
+(char-at "Apple" 0) ; => 65
+
+;; Выводить информацию достаточно легко
+(pr "Я" "Paren. ") (prn "Приятно познакомиться!")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 2. Переменные
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Вы можете создать или инициализировать переменную, используя (set)
+;; имя переменной может содержать любой символ, исключая: ();#"
+(set some-var 5) ; => 5
+some-var ; => 5
+
+;; Обращение к переменной, прежде не определенной, вызовет исключение
+; x ; => Неизвестная переменная: x : nil
+
+;; Локальное связывание: Используйте лямбда-вычисление! `a' и `b' связывается
+;; с `1' и `2' только в пределах (fn ...)
+((fn (a b) (+ a b)) 1 2) ; => 3
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. Коллекции
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Списки
+
+;; Списки подобны динамическому массиву (vector). (произвольный доступ равен O(1).)
+(cons 1 (cons 2 (cons 3 (list)))) ; => (1 2 3)
+;; `list' - это удобный конструктор списков с переменным числом элементов
+(list 1 2 3) ; => (1 2 3)
+;; и quote может также использоваться для литеральных значений списка
+(quote (+ 1 2)) ; => (+ 1 2)
+
+;; Можно еще использовать `cons', чтобы добавить элемент в начало списка
+(cons 0 (list 1 2 3)) ; => (0 1 2 3)
+
+;; Списки являются основным типом, поэтому для них предусмотрено *много* функций
+;; немного примеров из них:
+(map inc (list 1 2 3)) ; => (2 3 4)
+(filter (fn (x) (== 0 (% x 2))) (list 1 2 3 4)) ; => (2 4)
+(length (list 1 2 3 4)) ; => 4
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. Функции
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Используйте `fn' для создания функций.
+;; Функция всегда возвращает значение своего последнего выражения
+(fn () "Привет Мир") ; => (fn () Привет Мир) : fn
+
+;; Используйте скобки, чтобы вызвать все функции, в том числе лямбда-выражение
+((fn () "Привет Мир")) ; => "Привет Мир"
+
+;; Назначить функцию переменной
+(set hello-world (fn () "Привет Мир"))
+(hello-world) ; => "Привет Мир"
+
+;; Вы можете сократить это, используя синтаксический сахар определения функции:
+(defn hello-world2 () "Привет Мир")
+
+;; Как и выше, () - это список аргументов для функции
+(set hello
+ (fn (name)
+ (strcat "Привет " name)))
+(hello "Стив") ; => "Привет Стив"
+
+;; ... или, что эквивалентно, используйте синтаксический сахар определения:
+(defn hello2 (name)
+ (strcat "Привет " name))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 4. Равенство
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; для чисел используйте `=='
+(== 3 3.0) ; => true
+(== 2 1) ; => false
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 5. Поток управления
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Условный оператор
+
+(if true ; проверка выражения
+ "это - истина" ; тогда это выражение
+ "это - ложь") ; иначе другое выражение
+; => "это - истина"
+
+;;; Циклы
+
+;; Цикл for для чисел
+;; (for ИДЕНТИФИКАТОР НАЧАЛО КОНЕЦ ШАГ ВЫРАЖЕНИЕ ..)
+(for i 0 10 2 (pr i "")) ; => печатает 0 2 4 6 8 10
+(for i 0.0 10 2.5 (pr i "")) ; => печатает 0 2.5 5 7.5 10
+
+;; Цикл while
+((fn (i)
+ (while (< i 10)
+ (pr i)
+ (++ i))) 0) ; => печатает 0123456789
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 6. Изменение
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Используйте `set', чтобы назначить новое значение переменной или памяти
+(set n 5) ; => 5
+(set n (inc n)) ; => 6
+n ; => 6
+(set a (list 1 2)) ; => (1 2)
+(set (nth 0 a) 3) ; => 3
+a ; => (3 2)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 7. Макросы
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Макросы позволяют вам расширять синтаксис языка.
+;; Paren-макросы легкие.
+;; Фактически, (defn) - это макрос.
+(defmacro setfn (name ...) (set name (fn ...)))
+(defmacro defn (name ...) (def name (fn ...)))
+
+;; Давайте добавим инфиксную нотацию
+(defmacro infix (a op ...) (op a ...))
+(infix 1 + 2 (infix 3 * 4)) ; => 15
+
+;; Макросы приводят к неясному коду, т.е. вы можете затереть существующие переменные!
+;; Они являются кодопреобразующей конструкцией.
+```
diff --git a/ru-ru/perl-ru.html.markdown b/ru-ru/perl-ru.html.markdown
new file mode 100644
index 00000000..a907ba41
--- /dev/null
+++ b/ru-ru/perl-ru.html.markdown
@@ -0,0 +1,195 @@
+---
+category: language
+language: perl
+filename: learnperl-ru.pl
+contributors:
+ - ["Korjavin Ivan", "http://github.com/korjavin"]
+translators:
+ - ["Elena Bolshakova", "http://github.com/liruoko"]
+lang: ru-ru
+---
+
+Perl 5 -- высокоуровневый мощный язык с 25-летней историей.
+Особенно хорош для обработки разнообразных текстовых данных.
+
+Perl 5 работает более чем на 100 платформах, от портативных устройств
+до мейнфреймов, и подходит как для быстрого прототипирования,
+так и для крупных проектов.
+
+```perl
+# Комментарии начинаются с символа решетки.
+
+
+#### Типы переменных в Perl
+
+# Скалярные переменные начинаются с знака доллара $.
+# Имя переменной состоит из букв, цифр и знаков подчеркивания,
+# начиная с буквы или подчеркивания.
+
+### В Perl три основных типа переменных: скаляры, массивы, хеши.
+
+## Скаляры
+# Скаляр хранит отдельное значение:
+my $animal = "camel";
+my $answer = 42;
+
+# Скаляры могут быть строками, целыми и вещественными числами.
+# Когда требуется, Perl автоматически выполняет преобразования к нужному типу.
+
+## Массивы
+# Массив хранит список значений:
+my @animals = ("camel", "llama", "owl");
+my @numbers = (23, 42, 69);
+my @mixed = ("camel", 42, 1.23);
+
+
+## Хеши
+# Хеш хранит набор пар ключ/значение:
+
+my %fruit_color = ("apple", "red", "banana", "yellow");
+
+# Можно использовать оператор "=>" для большей наглядности:
+
+my %fruit_color = (
+ apple => "red",
+ banana => "yellow",
+ );
+
+# Важно: вставка и поиск в хеше выполняются за константное время,
+# независимо от его размера.
+
+# Скаляры, массивы и хеши подробно описаны в разделе perldata
+# (perldoc perldata).
+
+# Более сложные структуры данных можно получить, если использовать ссылки.
+# С помощью ссылок можно получить массив массивов хешей, в которых хранятся другие хеши.
+
+#### Условные операторы и циклы
+
+# В Perl есть большинсво привычных условных и циклических конструкций.
+
+if ( $var ) {
+ ...
+} elsif ( $var eq 'bar' ) {
+ ...
+} else {
+ ...
+}
+
+unless ( condition ) {
+ ...
+ }
+# Это более читаемый вариант для "if (!condition)"
+
+# Специфические Perl-овые пост-условия:
+print "Yow!" if $zippy;
+print "We have no bananas" unless $bananas;
+
+# while
+ while ( condition ) {
+ ...
+ }
+
+
+# for, foreach
+for ($i = 0; $i <= $max; $i++) {
+ ...
+ }
+
+foreach (@array) {
+ print "This element is $_\n";
+ }
+
+for my $el (@array) {
+ print "This element is $el\n";
+ }
+
+#### Регулярные выражения
+
+# Регулярные выражения занимают важное место в Perl-е,
+# и подробно описаны в разделах документации perlrequick, perlretut и других.
+# Вкратце:
+
+# Сопоставление с образцом
+if (/foo/) { ... } # выполняется, если $_ содержит "foo"
+if ($a =~ /foo/) { ... } # выполняется, если $a содержит "foo"
+
+# Простые замены
+
+$a =~ s/foo/bar/; # заменяет foo на bar в строке $a
+$a =~ s/foo/bar/g; # заменяет ВСЕ ВХОЖДЕНИЯ foo на bar в строке $a
+
+
+#### Файлы и ввод-вывод
+
+# Открыть файл на чтение или запись можно с помощью функции "open()".
+
+open(my $in, "<", "input.txt") or die "Can't open input.txt: $!";
+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>;
+my @lines = <$in>;
+
+#### Подпрограммы (функции)
+
+# Объявить функцию просто:
+
+sub logger {
+ my $logmessage = shift;
+ open my $logfile, ">>", "my.log" or die "Could not open my.log: $!";
+ print $logfile $logmessage;
+}
+
+# Теперь можно использовать эту функцию так же, как и встроенные:
+
+logger("We have a logger subroutine!");
+```
+
+#### Perl-модули
+
+Perl-овые модули предоставляют широкий набор функциональности,
+так что вы можете не изобретать заново велосипеды, а просто скачать
+нужный модуль с CPAN (http://www.cpan.org/).
+Некоторое количество самых полезных модулей включено в стандартную
+поставку Perl.
+
+Раздел документации perlfaq содержит вопросы и ответы о многих частых
+задачах, и часто предлагает подходящие CPAN-модули.
+
+
+#### Unicode
+
+Вам наверняка понадобится работать с не-ASCII текстами.
+Добавьте эти прагмы в начало скрипта:
+
+```perl
+use utf8;
+use open ':std' => ':utf8';
+```
+
+Подробнее читайте в perldoc, разделы perlunicode и open.
+
+
+#### strict, warnings
+
+Прагмы strict и warnings включают полезные проверки во время компиляции:
+
+```perl
+use strict;
+use warnings;
+```
+
+Подробнее смотрите perldoc strict и perldoc warnings.
+
+
+#### Смотрите также
+
+ - [perl-tutorial](http://perl-tutorial.org/)
+ - [обучающий раздел на www.perl.com](http://www.perl.org/learn.html)
+ - [perldoc в вебе](http://perldoc.perl.org/)
+ - встроенная справка : `perldoc perlintro`
diff --git a/ru-ru/php-ru.html.markdown b/ru-ru/php-ru.html.markdown
index 53b2f916..af77a9ca 100644
--- a/ru-ru/php-ru.html.markdown
+++ b/ru-ru/php-ru.html.markdown
@@ -5,6 +5,7 @@ contributors:
- ["Trismegiste", "https://github.com/Trismegiste"]
translators:
- ["SlaF", "https://github.com/SlaF"]
+ - ["Corpsee", "https://github.com/corpsee"]
lang: ru-ru
filename: learnphp-ru.php
---
@@ -14,8 +15,8 @@ filename: learnphp-ru.php
```php
<?php // PHP код должен быть заключен в теги <?php
-// Если ваш файл содержит только PHP код, то можно
-// пропустить закрывающийся ?>
+// Если ваш файл содержит только PHP-код, то можно
+пропустить закрывающий ?>
// А так начинаются комментарии
@@ -30,10 +31,10 @@ filename: learnphp-ru.php
print('Hello '); // Напечатать "Hello " без перевода строки
// () необязательно применять для print и echo
-echo "World\n"; // Печатать "World" и перейти на новую строку.
-// (все утверждения должны заканчиваться ;)
+echo "World\n"; // Напечатать "World" и перейти на новую строку.
+// (все утверждения должны заканчиваться точкой с запятой)
-// Любые символы за пределами закрывающегося тега выводятся автоматически:
+// Любые символы за пределами закрывающего тега выводятся автоматически:
?>
Hello World Again!
<?php
@@ -44,9 +45,9 @@ Hello World Again!
*/
// Переменные начинаются с символа $.
-// Правильное имя переменной начинается с буквы или знака подчеркивания,
-// и может содержать любые цифры, буквы, или знаки подчеркивания.
-// Не рекомендуется использовать кирилические символы в именах (прим. пер.)
+// Правильное имя переменной начинается с буквы или символа подчеркивания,
+// за которым следует любое количество букв, цифр или символов подчеркивания.
+// Не рекомендуется использовать кириллические символы в именах (прим. пер.)
// Логические значения нечувствительны к регистру
$boolean = true; // или TRUE или True
@@ -54,9 +55,14 @@ $boolean = false; // или FALSE или False
// Целые числа
$int1 = 12; // => 12
-$int2 = -12; // => -12-
+$int2 = -12; // => -12
$int3 = 012; // => 10 (ведущий 0 обозначает восьмеричное число)
-$int4 = 0x0F; // => 15 (ведущие символы 0x означает шестнадцатеричное число)
+$int4 = 0x0F; // => 15 (ведущие символы 0x означают шестнадцатеричное число)
+
+// Двоичная запись integer доступна начиная с PHP 5.4.0.
+$int5 = 0b11111111; // 255 (0b в начале означает двоичное число)
+// Удаление переменной
+unset($int1);
// Дробные числа
$float = 1.234;
@@ -86,7 +92,9 @@ $dbl_quotes = "This is a $sgl_quotes."; // => 'This is a $String.'
$escaped = "This contains a \t tab character.";
$unescaped = 'This just contains a slash and a t: \t';
-// Заключайте переменные в фигурные скобки если это необходимо
+// Заключайте переменные в фигурные скобки, если это необходимо
+$apples = "I have {$number} apples to eat.";
+$oranges = "I have ${number} oranges to eat.";
$money = "I have $${number} in the bank.";
// Начиная с PHP 5.3, синтаксис nowdocs может использоваться для
@@ -105,6 +113,9 @@ END;
// Строки соединяются при помощи .
echo 'This string ' . 'is concatenated';
+// echo можно передавать строки как параметры
+echo 'Multiple', 'Parameters', 'Valid'; // печатает 'MultipleParametersValid'
+
/********************************
* Константы
@@ -113,20 +124,21 @@ echo 'This string ' . 'is concatenated';
// Константа определяется при помощи define()
// и никогда не может быть изменена во время выполнения программы!
-// Правильное имя константы начинается с буквы или символа подчеркивания,
-// и содержит любое колличество букв, цифр и знаков подчеркивания.
+// Правильное имя константы начинается с буквы или символа подчеркивания
+// и содержит любое колличество букв, цифр или символов подчеркивания.
define("FOO", "something");
-// Доступ к константе возможен через прямое указание её имени
-echo 'This outputs '.FOO;
+// Доступ к константе возможен через прямое указание её имени без знака $
+echo FOO; // печатает 'something'
+echo 'This outputs ' . FOO; // печатает 'This outputs something'
/********************************
* Массивы
*/
-// Все массивы в PHP - это ассоциативные массивы или хеши,
+// Все массивы в PHP - это ассоциативные массивы
-// Ассоциативные массивы, известные в других языках как хеш-карты.
+// Ассоциативные массивы, известные в других языках как HashMap.
// Работает во всех версиях РHP
$associative = array('One' => 1, 'Two' => 2, 'Three' => 3);
@@ -135,11 +147,20 @@ $associative = array('One' => 1, 'Two' => 2, 'Three' => 3);
$associative = ['One' => 1, 'Two' => 2, 'Three' => 3];
echo $associative['One']; // печатает 1
+// Добавить элемент в ассоциативный массив
+$associative['Four'] = 4;
+
// Список тоже содержит целочисленные ключи
$array = ['One', 'Two', 'Three'];
echo $array[0]; // => "One"
+// Добавить элемент в конец массива
+$array[] = 'Four';
+// или
+array_push($array, 'Five');
+// удалить элемент из массива
+unset($array[3]);
/********************************
* Вывод
@@ -179,6 +200,10 @@ $y = 0;
echo $x; // => 2
echo $z; // => 0
+// Вывести тип и значение переменной в stdout
+var_dump($z); // печатает int(0)
+// Напечатать переменную в stdout в удобочитаемом виде
+print_r($array); // печатает: Array ( [0] => One [1] => Two [2] => Three )
/********************************
* Логические выражения
@@ -188,7 +213,7 @@ $b = '0';
$c = '1';
$d = '1';
-// Утверждение (assert) выдает предупреждение если аргумент не true
+// Утверждение (assert) выдает предупреждение, если его аргумент не true
// Эти сравнения всегда будут истинными, даже если типы будут различаться
assert($a == $b); // "равно"
@@ -199,13 +224,22 @@ assert($c > $b); // больше
assert($a <= $b); // меньше или равно
assert($c >= $d); // больше или равно
-// Следующие утверждения истинны если переменные имеют одинаковый тип.
+// Следующие утверждения истинны, если переменные имеют одинаковые тип.
assert($c === $d);
assert($a !== $d);
assert(1 == '1');
assert(1 !== '1');
-// Переменные могут изменять тип, в зависимости от их использования.
+// 'Spaceship' оператор (с PHP 7) используется для сравнения двух выражений.
+// Возвращает -1, 0 или 1, когда выражение слева меньше, равно или больше
+// выражения справа.
+$a = 100;
+$b = 1000;
+
+echo $a <=> $a; // 0, выражения равны
+echo $a <=> $b; // -1, $a < $b
+echo $b <=> $a; // 1, $b > $a
+// Переменные могут изменять тип в зависимости от их использования.
$integer = 1;
echo $integer + $integer; // => 2
@@ -235,7 +269,7 @@ $var = null; // Null
$integer = 10;
$boolen = settype($integer, "string") // теперь $integer имеет строковый тип
-// settype возвращает true - если преобразование удалось и false в противном случае
+// settype возвращает true, если преобразование удалось и false в противном случае
/********************************
* Управляющие структуры
@@ -260,6 +294,11 @@ if (false) {
// Тернарный оператор
print (false ? 'Does not get printed' : 'Does');
+// сокращенная запись тернарного оператора с PHP 5.3
+// эквивалентно "$x ? $x : 'Does'"
+$x = false;
+print($x ?: 'Does');
+
$x = 0;
if ($x === '0') {
print 'Does not print';
@@ -283,35 +322,35 @@ This is displayed otherwise.
// Использование switch.
switch ($x) {
case '0':
- print 'Switch does type coercion';
- break; // You must include a break, or you will fall through
- // to cases 'two' and 'three'
+ print 'Switch использует неточное сравнение';
+ break; // вы должны использовать break, иначе PHP будет продолжать
+ // исполнять команды следующих секций case 'two' и 'three'
case 'two':
case 'three':
- // Do something if $variable is either 'two' or 'three'
+ // делаем что-то, если $x == 'two' или $x == 'three'
break;
default:
- // Do something by default
+ // делаем что-то по умолчанию
}
// Циклы: while, do...while и for
$i = 0;
while ($i < 5) {
echo $i++;
-}; // Prints "01234"
+}; // печатает "01234"
echo "\n";
$i = 0;
do {
echo $i++;
-} while ($i < 5); // Prints "01234"
+} while ($i < 5); // печатает "01234"
echo "\n";
for ($x = 0; $x < 10; $x++) {
echo $x;
-} // Prints "0123456789"
+} // печатает "0123456789"
echo "\n";
@@ -320,7 +359,7 @@ $wheels = ['bicycle' => 2, 'car' => 4];
// Циклы foreach могут обходить массивы
foreach ($wheels as $wheel_count) {
echo $wheel_count;
-} // Prints "24"
+} // Напечатает "24"
echo "\n";
@@ -334,17 +373,17 @@ echo "\n";
$i = 0;
while ($i < 5) {
if ($i === 3) {
- break; // Exit out of the while loop
+ break; // выйти из цикла while
}
echo $i++;
-} // Prints "012"
+} // Напечатает "012"
for ($i = 0; $i < 5; $i++) {
if ($i === 3) {
- continue; // Skip this iteration of the loop
+ continue; // пропустить текущую итерацию цикла
}
echo $i;
-} // Prints "0124"
+} // печатает "0124"
/********************************
@@ -359,7 +398,7 @@ function my_function () {
echo my_function(); // => "Hello"
// Правильное имя функции начинается с буквы или символа подчеркивания
-// и состоит из букв, цифр или знаков подчеркивания.
+// и состоит из букв, цифр или символов подчеркивания.
function add ($x, $y = 1) { // $y по умолчанию равно 1
$result = $x + $y;
@@ -369,7 +408,7 @@ function add ($x, $y = 1) { // $y по умолчанию равно 1
echo add(4); // => 5
echo add(4, 2); // => 6
-// $result недоступна за пределами функции
+// $result недоступен за пределами функции
// print $result; // Выдает предупреждение
// Начиная с PHP 5.3 вы можете объявлять анонимные функции:
@@ -402,27 +441,25 @@ echo $function_name(1, 2); // => 3
/********************************
- * Includes
+ * Включения
*/
<?php
// PHP код внутри включаемого файла должен начинаться с тега PHP.
include 'my-file.php';
-// Код в файле my-file.php теперь доступен в текущем в текущем пространстве имен.
-// Если файл не удалось включить, будет выдано предупреждение.
+// Код в файле my-file.php теперь доступен в текущем пространстве имен.
+// Если файл не удалось подключить, то будет выдано предупреждение.
include_once 'my-file.php';
-// Если код в файле my-file.php уже был включен, он не будет включен повторно.
-// Это предотвращает ошибку повторного включения файла.
+// Если код в файле my-file.php уже был подключен, он не будет подключен повторно.
+// Это предотвращает ошибку повторного подключения файла.
require 'my-file.php';
require_once 'my-file.php';
-// Same as include(), except require() will cause a fatal error if the
-// file cannot be included.
// Действует также как и include(), но если файл не удалось подключить,
-// функция выдает неисправимую ошибку
+// функция выдает фатальную ошибку
// Содержимое файла my-include.php:
<?php
@@ -448,23 +485,23 @@ $value = include 'my-include.php';
class MyClass
{
- const MY_CONST = 'value'; // A constant
+ const MY_CONST = 'value'; // Константа
static $staticVar = 'static';
- // Properties must declare their visibility
+ // Свойства объявляются с указанием их видимости
public $property = 'public';
public $instanceProp;
- protected $prot = 'protected'; // Accessible from the class and subclasses
- private $priv = 'private'; // Accessible within the class only
+ protected $prot = 'protected'; // Свойство доступно только потомкам и самому классу
+ private $priv = 'private'; // Свойство доступно только самому классу
- // Create a constructor with __construct
+ // Конструктор описывается с помощью __construct
public function __construct($instanceProp) {
- // Access instance variables with $this
+ // Доступ к эземпляру класса с помощью $this
$this->instanceProp = $instanceProp;
}
- // Methods are declared as functions inside a class
+ // Методы объявляются как функции принадлежащие классу
public function myMethod()
{
print 'MyClass';
@@ -484,7 +521,7 @@ echo MyClass::MY_CONST; // Выведет 'value';
echo MyClass::$staticVar; // Выведет 'static';
MyClass::myStaticMethod(); // Выведет 'I am static';
-// Новый экземпляр класса используя new
+// Создание нового экземпляра класса используя new
$my_class = new MyClass('An instance property');
// Если аргументы отсутствуют, можно не ставить круглые скобки
@@ -502,7 +539,7 @@ class MyOtherClass extends MyClass
echo $this->prot;
}
- // Override a method
+ // Переопределение родительского метода
function myMethod()
{
parent::myMethod();
@@ -595,7 +632,7 @@ class SomeOtherClass implements InterfaceOne, InterfaceTwo
* Трейты
*/
-// Трейты появились в PHP 5.4.0 и объявляются при помощи ключевого слова trait
+// Трейты появились в PHP 5.4 и объявляются при помощи ключевого слова trait
trait MyTrait
{
@@ -611,7 +648,7 @@ class MyTraitfulClass
}
$cls = new MyTraitfulClass();
-$cls->myTraitMethod(); // Prints "I have MyTrait"
+$cls->myTraitMethod(); // Напечатает "I have MyTrait"
/********************************
@@ -652,12 +689,128 @@ 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
+*/
+
+
+/**********************
+* Магические константы
+*
+*/
+
+// Возвращает имя текущего класса. Должно быть использовано внутри класса.
+echo "Current class name is " . __CLASS__;
+
+// Возвращает полный путь текущей папки из которой вызван файл.
+echo "Current directory is " . __DIR__;
+
+ // Обычно используют в таких случаях:
+ require __DIR__ . '/vendor/autoload.php';
+
+// Возвращает полный путь к текущему файлу.
+echo "Current file path is " . __FILE__;
+
+// Возвращает имя текущей функции.
+echo "Current function name is " . __FUNCTION__;
+
+// Возвращает номер текущей линии.
+echo "Current line number is " . __LINE__;
+
+// Возвращает имя текущего метода. Возвращает только если вызван внутри метода.
+echo "Current method is " . __METHOD__;
+
+// Возвращает имя текущего пространства имен.
+echo "Current namespace is " . __NAMESPACE__;
+
+// Возвращает имя текущего трейта.
+// Возвращает только если испольщуется внутри трейта.
+echo "Current namespace is " . __TRAIT__;
+
+
+/**********************
+* Обработка ошибок
+*
+*/
+
+// Простую обработку ошибок можно произвести спомощью try catch блока.
+
+try {
+ // Выполняем что-то
+} catch (Exception $e) {
+ // Обработка исключения
+}
+
+// При использовании try catch блока в области вилимости, стоит использовать
+// следующий подход:
+
+try {
+ // Do something
+} catch (\Exception $e) {
+ // Обработка исключения
+}
+
+// Специальное(кастомное) исключение - exceptions
+
+class MyException extends Exception {}
+
+try {
+
+ $condition = true;
+
+ if ($condition) {
+ throw new MyException('Something just happend');
+ }
+
+} catch (MyException $e) {
+ // Обработка исключения
+}
+
```
## Смотрите также:
-Посетите страницу [официальной документации PHP](http://www.php.net/manual/) для справки.
+Посетите страницу [официальной документации PHP](http://www.php.net/manual/) для справки.
+
Если вас интересуют полезные приемы использования PHP посетите [PHP The Right Way](http://www.phptherightway.com/).
+
Если вы раньше пользовались языком с хорошей организацией пакетов, посмотрите [Composer](http://getcomposer.org/).
-Для изучения стандартов использования языка посетите PHP Framework Interoperability Group's [PSR standards](https://github.com/php-fig/fig-standards).
+
+Для изучения стандартов использования языка посетите PHP Framework Interoperability Group's [PSR standards](https://github.com/php-fig/fig-standards).
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 d59d3e21..43142eff 100644
--- a/ru-ru/python-ru.html.markdown
+++ b/ru-ru/python-ru.html.markdown
@@ -10,20 +10,20 @@ filename: learnpython-ru.py
---
Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из
-самых популярных языков. Я люблю его за понятный и доходчивый синтаксис — это
-почти что исполняемый псевдокод.
+самых популярных языков. Я влюбился в Python за понятный и доходчивый синтаксис — это
+почти исполняемый псевдокод.
С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh)
или louiedinh [at] [почтовый сервис Google]
-Замечание: Эта статья относится к Python 2.7, но должно работать и в Python 2.x.
-Скоро будет версия и для Python 3!
+Замечание: Эта статья относится к Python 2.7, но должно работать и в других версиях Python 2.x.
+Чтобы изучить Python 3.x, обратитесь к статье по Python 3.
```python
# Однострочные комментарии начинаются с символа решётки.
""" Многострочный текст может быть
записан, используя 3 знака " и обычно используется
- в качестве комментария
+ в качестве встроенной документации
"""
####################################################
@@ -43,7 +43,7 @@ filename: learnpython-ru.py
# целых чисел, и результат автоматически округляется в меньшую сторону.
5 / 2 #=> 2
-# Чтобы научиться делить, сначала нужно немного узнать о числах
+# Чтобы делить правильно, сначала нужно немного узнать о числах
# с плавающей запятой.
2.0 # Это число с плавающей запятой
11.0 / 4.0 #=> 2.75 Вооот... Так гораздо лучше
@@ -59,14 +59,22 @@ filename: learnpython-ru.py
7 % 3 # => 1
# Возведение в степень
-2 ** 4 # => 16
+2**4 # => 16
# Приоритет операций указывается скобками
(1 + 3) * 2 #=> 8
-# Логические (булевы) значения являются примитивами
-True
-False
+# Логические операторы
+# Обратите внимание: ключевые слова «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
# Для отрицания используется ключевое слово not
not True #=> False
@@ -86,7 +94,7 @@ not False #=> True
2 <= 2 #=> True
2 >= 2 #=> True
-# Сравнения могут быть соединены в цепь!
+# Сравнения могут быть записаны цепочкой!
1 < 2 < 3 #=> True
2 < 3 < 2 #=> False
@@ -94,9 +102,12 @@ not False #=> True
"Это строка."
'Это тоже строка.'
-# И строки тоже могут складываться!
+# И строки тоже можно складывать!
"Привет " + "мир!" #=> "Привет мир!"
+# ... или умножать
+"Привет" * 3 # => "ПриветПриветПривет"
+
# Со строкой можно работать, как со списком символов
"Это строка"[0] #=> 'Э'
@@ -122,7 +133,7 @@ None is None #=> True
# очень полезен при работе с примитивными типами, но
# зато просто незаменим при работе с объектами.
-# None, 0, и пустые строки/списки равны False.
+# None, 0 и пустые строки/списки равны False.
# Все остальные значения равны True
0 == False #=> True
"" == False #=> True
@@ -132,12 +143,14 @@ None is None #=> True
## 2. Переменные и коллекции
####################################################
-# У Python есть функция Print, доступная в версиях 2.7 и 3,
-print("Я Python. Приятно познакомиться!")
-# ...и старый оператор print, доступный в версиях 2.x, но удалённый в версии 3.
-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
@@ -151,9 +164,13 @@ some_other_var # Выбрасывает ошибку именования
# Списки хранят последовательности
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]
@@ -166,13 +183,17 @@ li.append(3) # [1, 2, 4, 3].
# Обращайтесь со списком, как с обычным массивом
li[0] #=> 1
+# Присваивайте новые значения уже инициализированным индексам с помощью =
+li[0] = 42
+li[0] # => 42
+li[0] = 1 # Обратите внимание: возвращаемся на исходное значение
# Обратимся к последнему элементу
li[-1] #=> 3
# Попытка выйти за границы массива приведёт к ошибке индекса
li[4] # Выдаёт IndexError
-# Можно обращаться к диапазону, используя "кусочный синтаксис" (slice syntax)
+# Можно обращаться к диапазону, используя так называемые срезы
# (Для тех, кто любит математику, это называется замкнуто-открытый интервал).
li[1:3] #=> [2, 4]
# Опускаем начало
@@ -183,14 +204,15 @@ li[:3] #=> [1, 2, 4]
li[::2] # =>[1, 4]
# Переворачиваем список
li[::-1] # => [3, 4, 2, 1]
-# Используйте сочетания всего вышеназванного для выделения более сложных кусков
+# Используйте сочетания всего вышеназванного для выделения более сложных срезов
# li[начало:конец:шаг]
# Удаляем произвольные элементы из списка оператором del
-del li[2] # [1, 2, 3]
+del li[2] # li теперь [1, 2, 3]
-# Вы можете складывать списки
+# Вы можете складывать, или, как ещё говорят, конкатенировать списки
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]
@@ -220,13 +242,13 @@ d, e, f = 4, 5, 6
# Обратите внимание, как легко поменять местами значения двух переменных
e, d = d, e # теперь d == 5, а e == 4
-
# Словари содержат ассоциативные массивы
empty_dict = {}
# Вот так описывается предзаполненный словарь
filled_dict = {"one": 1, "two": 2, "three": 3}
-# Значения ищутся по ключу с помощью оператора []
+# Значения извлекаются так же, как из списка, с той лишь разницей,
+# что индекс — у словарей он называется ключом — не обязан быть числом
filled_dict["one"] #=> 1
# Можно получить все ключи в виде списка с помощью метода keys
@@ -245,24 +267,33 @@ filled_dict.values() #=> [3, 2, 1]
# Попытка получить значение по несуществующему ключу выбросит ошибку ключа
filled_dict["four"] # KeyError
-# Чтобы избежать этого, используйте метод get
+# Чтобы избежать этого, используйте метод 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 не устанавливает значение элемента словаря)
-# Метод 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
# Множества содержат... ну, в общем, множества
+# (которые похожи на списки, только в них не может быть дублирующихся элементов)
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])
+
# Начиная с Python 2.7, вы можете использовать {}, чтобы объявить множество
filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4}
@@ -345,7 +376,7 @@ try:
# Чтобы выбросить ошибку, используется raise
raise IndexError("Это ошибка индекса")
except IndexError as e:
- # pass это просто отсутствие оператора. Обычно здесь происходит
+ # pass — это просто отсутствие оператора. Обычно здесь происходит
# восстановление после ошибки.
pass
except (TypeError, NameError):
@@ -362,7 +393,7 @@ 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
@@ -370,15 +401,17 @@ add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвр
# Другой способ вызова функции — вызов с именованными аргументами
add(y=6, x=5) # Именованные аргументы можно указывать в любом порядке.
-# Вы можете определить функцию, принимающую изменяемое число аргументов
+# Вы можете определить функцию, принимающую переменное число аргументов,
+# которые будут интерпретированы как кортеж, если вы не используете *
def varargs(*args):
return args
varargs(1, 2, 3) #=> (1,2,3)
-# А также можете определить функцию, принимающую изменяемое число
-# именованных аргументов
+# А также можете определить функцию, принимающую переменное число
+# именованных аргументов, которые будут интерпретированы как словарь,
+# если вы не используете **
def keyword_args(**kwargs):
return kwargs
@@ -396,13 +429,21 @@ 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)
+
# Область определения функций
x = 5
@@ -420,7 +461,7 @@ def setGlobalX(num):
setX(43)
setGlobalX(6)
-# В Python есть функции первого класса
+# В Python функции — «объекты первого класса»
def create_adder(x):
def adder(y):
return x + y
@@ -514,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-файлы. Вы
# можете писать свои модули и импортировать их. Название
@@ -544,7 +588,7 @@ def double_numbers(iterable):
# мы используем подчёркивание в конце
xrange_ = xrange(1, 900000000)
-# Будет удваивать все числа, пока результат не будет >= 30
+# Будет удваивать все числа, пока результат не превысит 30
for i in double_numbers(xrange_):
print(i)
if i >= 30:
diff --git a/ru-ru/python3-ru.html.markdown b/ru-ru/python3-ru.html.markdown
index 637c0157..2b6b59a7 100644
--- a/ru-ru/python3-ru.html.markdown
+++ b/ru-ru/python3-ru.html.markdown
@@ -10,7 +10,7 @@ filename: learnpython3-ru.py
---
Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из
-самых популярных языков. Я люблю его за понятный и доходчивый синтаксис — это
+самых популярных языков. Я влюбился в Python за понятный и доходчивый синтаксис — это
почти что исполняемый псевдокод.
С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh)
@@ -56,7 +56,7 @@ filename: learnpython3-ru.py
7 % 3 # => 1
# Возведение в степень
-2 ** 4 # => 16
+2**4 # => 16
# Приоритет операций указывается скобками
(1 + 3) * 2 #=> 8
@@ -69,6 +69,18 @@ False
not True #=> False
not False #=> True
+# Логические операторы
+# Обратите внимание: ключевые слова «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
+
# Равенство — это ==
1 == 1 #=> True
2 == 1 #=> False
@@ -91,7 +103,7 @@ not False #=> True
"Это строка."
'Это тоже строка.'
-# И строки тоже могут складываться! Хотя лучше этого не делайте.
+# И строки тоже могут складываться! Хотя лучше не злоупотребляйте этим.
"Привет " + "мир!" #=> "Привет мир!"
# Со строкой можно работать, как со списком символов
@@ -134,10 +146,10 @@ bool({}) #=> False
## 2. Переменные и коллекции
####################################################
-# У Python есть функция Print
+# В Python есть функция Print
print("Я Python. Приятно познакомиться!")
-# Необязательно объявлять переменные перед их инициализацией.
+# Объявлять переменные перед инициализацией не нужно.
# По соглашению используется нижний_регистр_с_подчёркиваниями
some_var = 5
some_var #=> 5
@@ -149,7 +161,7 @@ some_unknown_var # Выбрасывает ошибку именования
# Списки хранят последовательности
li = []
-# Можно сразу начать с заполненным списком
+# Можно сразу начать с заполненного списка
other_li = [4, 5, 6]
# Объекты добавляются в конец списка методом append
@@ -170,7 +182,7 @@ li[-1] #=> 3
# Попытка выйти за границы массива приведёт к ошибке индекса
li[4] # Выдаёт IndexError
-# Можно обращаться к диапазону, используя "кусочный синтаксис" (slice syntax)
+# Можно обращаться к диапазону, используя так называемые срезы
# (Для тех, кто любит математику, это называется замкнуто-открытый интервал).
li[1:3] #=> [2, 4]
# Опускаем начало
@@ -181,13 +193,14 @@ li[:3] #=> [1, 2, 4]
li[::2] # =>[1, 4]
# Переворачиваем список
li[::-1] # => [3, 4, 2, 1]
-# Используйте сочетания всего вышеназванного для выделения более сложных кусков
+# Используйте сочетания всего вышеназванного для выделения более сложных срезов
# li[начало:конец:шаг]
# Удаляем произвольные элементы из списка оператором del
del li[2] # [1, 2, 3]
-# Вы можете складывать списки
+# Вы можете складывать, или, как ещё говорят, конкатенировать списки
+# Обратите внимание: значения li и other_li при этом не изменились.
li + other_li #=> [1, 2, 3, 4, 5, 6] — Замечание: li и other_li не изменяются
# Объединять списки можно методом extend
@@ -224,10 +237,11 @@ empty_dict = {}
# Вот так описывается предзаполненный словарь
filled_dict = {"one": 1, "two": 2, "three": 3}
-# Значения ищутся по ключу с помощью оператора []
+# Значения извлекаются так же, как из списка, с той лишь разницей,
+# что индекс — у словарей он называется ключом — не обязан быть числом
filled_dict["one"] #=> 1
-# Все значения в виде списка получаются с помощью метода keys().
+# Все ключи в виде списка получаются с помощью метода keys().
# Его вызов нужно обернуть в list(), так как обратно мы получаем
# итерируемый объект, о которых поговорим позднее.
list(filled_dict.keys()) # => ["three", "two", "one"]
@@ -247,7 +261,7 @@ list(filled_dict.values()) # => [3, 2, 1]
# Попытка получить значение по несуществующему ключу выбросит ошибку ключа
filled_dict["four"] # KeyError
-# Чтобы избежать этого, используйте метод get
+# Чтобы избежать этого, используйте метод get()
filled_dict.get("one") #=> 1
filled_dict.get("four") #=> None
# Метод get также принимает аргумент по умолчанию, значение которого будет
@@ -259,6 +273,10 @@ filled_dict.get("four", 4) #=> 4
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» из словаря
@@ -345,7 +363,7 @@ try:
# Чтобы выбросить ошибку, используется raise
raise IndexError("Это ошибка индекса")
except IndexError as e:
- # pass это просто отсутствие оператора. Обычно здесь происходит
+ # pass — это просто отсутствие оператора. Обычно здесь происходит
# восстановление после ошибки.
pass
except (TypeError, NameError):
@@ -393,7 +411,7 @@ list(filled_dict.keys()) #=> Возвращает ["one", "two", "three"]
# Используйте 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
@@ -401,14 +419,14 @@ add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвр
# Другой способ вызова функции — вызов с именованными аргументами
add(y=6, x=5) # Именованные аргументы можно указывать в любом порядке.
-# Вы можете определить функцию, принимающую изменяемое число аргументов
+# Вы можете определить функцию, принимающую переменное число аргументов
def varargs(*args):
return args
varargs(1, 2, 3) #=> (1,2,3)
-# А также можете определить функцию, принимающую изменяемое число
+# А также можете определить функцию, принимающую переменное число
# именованных аргументов
def keyword_args(**kwargs):
return kwargs
@@ -427,7 +445,7 @@ 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)
@@ -451,7 +469,7 @@ def setGlobalX(num):
setX(43)
setGlobalX(6)
-# В Python функции — «объекты первого класса». Это означает, что их можно использовать наравне с любыми другими значениями
+# В Python функции — «объекты первого класса»
def create_adder(x):
def adder(y):
return x + y
@@ -531,7 +549,7 @@ Human.grunt() #=> "*grunt*"
# Вы можете импортировать модули
import math
-print(math.sqrt(16)) #=> 4
+print(math.sqrt(16)) #=> 4.0
# Вы можете импортировать отдельные функции модуля
from math import ceil, floor
@@ -575,7 +593,7 @@ def double_numbers(iterable):
range_ = range(1, 900000000)
# Будет удваивать все числа, пока результат не превысит 30
-for i in double_numbers(xrange_):
+for i in double_numbers(range_):
print(i)
if i >= 30:
break
diff --git a/ru-ru/qt-ru.html.markdown b/ru-ru/qt-ru.html.markdown
new file mode 100644
index 00000000..d0a70c9d
--- /dev/null
+++ b/ru-ru/qt-ru.html.markdown
@@ -0,0 +1,158 @@
+---
+category: tool
+tool: Qt Framework
+language: c++
+filename: learnqt-ru.cpp
+contributors:
+ - ["Aleksey Kholovchuk", "https://github.com/vortexxx192"]
+translators:
+ - ["Evan K.", "https://github.com/justblah"]
+lang: ru-ru
+---
+
+**Qt** является широко известным фреймворком для разработки кросс-платформенного программного обеспечения, которое может быть запущено на различных программно-аппаратных платформах практически без изменений в коде, сохраняя при этом мощность и скорость нативных приложений. Хоть **Qt** и был изначально написан на *C++*, у него есть реализации и на других языках: *PyQt*, *QtRuby*, *PHP-Qt* и т.д.
+
+**Qt** отлично подходит для создания приложений с графическим пользовательским интерфейсом (GUI). Это руководство о том, как сделать это на *C++*.
+
+```c++
+/*
+ * Начнём по-старинке
+ */
+
+// все header файлы импортированные из Qt начинаются с заглавной 'Q'
+#include <QApplication>
+#include <QLineEdit>
+
+int main(int argc, char *argv[]) {
+ // создаем объект для управления данными приложения
+ QApplication app(argc, argv);
+
+ // создаем редактируемую строку и отобразим её на экране
+ QLineEdit lineEdit("Hello world!");
+ lineEdit.show();
+
+ // запускаем цикл для обработки событий (event loop)
+ return app.exec();
+}
+```
+
+GUI часть **Qt** полностью состоит из *виджетов* и *связей* между ними.
+
+[(EN) ПОДРОБНЕЕ О ВИДЖЕТАХ](http://doc.qt.io/qt-5/qtwidgets-index.html)
+
+```c++
+/*
+ * В этом примере мы отобразим надпись с кнопкой.
+ * Надпись будет появляться после нажатия на кнопку.
+ *
+ * Код на Qt говорит сам за себя.
+ */
+
+#include <QApplication>
+#include <QDialog>
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QLabel>
+
+int main(int argc, char *argv[]) {
+ QApplication app(argc, argv);
+
+ QDialog dialogWindow;
+ dialogWindow.show();
+
+ // добавляем вертикальное расположение
+ QVBoxLayout layout;
+ dialogWindow.setLayout(&layout);
+
+ QLabel textLabel("Thanks for pressing that button");
+ layout.addWidget(&textLabel);
+ textLabel.hide();
+
+ QPushButton button("Press me");
+ layout.addWidget(&button);
+
+ // отображаем скрытую надпись после нажатия на кнопку
+ QObject::connect(&button, &QPushButton::pressed,
+ &textLabel, &QLabel::show);
+
+ return app.exec();
+}
+```
+Обратите внимание на метод *QObject::connect*. Этот метод соединяет *СИГНАЛЫ* одного объекта со *СЛОТАМИ* другого.
+
+**Сигналы** отправляются когда с объектами происходят отпределённые события, например, сигнал *нажатие* отправляется когда пользователь нажимает на объект типа QPushButton.
+
+**Слоты** это *действия*, которые могут быть выполнены в ответ на полученные сигналы.
+
+[(EN) ПОДРОБНЕЕ О СЛОТАХ И СИГНАЛАХ](http://doc.qt.io/qt-4.8/signalsandslots.html)
+
+
+Далее рассмотрим, как можно не только использовать стандартные виджеты, но и расширять их поведение с помощью наследования. Давайте создадим кнопку и посчитаем, сколько раз она была нажата. Для этого мы определяем наш собственный класс *CounterLabel*. Он должен быть объявлен в отдельном файле из-за специфической архитектуры Qt.
+
+```c++
+// counterlabel.hpp
+
+#ifndef COUNTERLABEL
+#define COUNTERLABEL
+
+#include <QLabel>
+
+class CounterLabel : public QLabel {
+ Q_OBJECT // макрос Qt, обязателен для всех виджетов
+
+public:
+ CounterLabel() : counter(0) {
+ setText("Counter has not been increased yet"); // метод QLabel
+ }
+
+public slots:
+ // действие, которое будет вызвано в ответ на нажатие
+ void increaseCounter() {
+ setText(QString("Counter value: %1").arg(QString::number(++counter)));
+ }
+
+private:
+ int counter;
+};
+
+#endif // COUNTERLABEL
+```
+
+```c++
+// main.cpp
+// Почти тоже самое, что и в предыдущем примере
+
+#include <QApplication>
+#include <QDialog>
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QString>
+#include "counterlabel.hpp"
+
+int main(int argc, char *argv[]) {
+ QApplication app(argc, argv);
+
+ QDialog dialogWindow;
+ dialogWindow.show();
+
+ QVBoxLayout layout;
+ dialogWindow.setLayout(&layout);
+
+ CounterLabel counterLabel;
+ layout.addWidget(&counterLabel);
+
+ QPushButton button("Push me once more");
+ layout.addWidget(&button);
+ QObject::connect(&button, &QPushButton::pressed,
+ &counterLabel, &CounterLabel::increaseCounter);
+
+ return app.exec();
+}
+```
+
+## На почитать
+Это всё! Конечно, фреймворк Qt намного объемнее, чем часть, которая была рассмотрена в этом руководстве, так что будьте готовы читать и практиковаться.
+
+[(EN) ДОКУМЕНТАЦИЯ](http://wiki.qt.io/Main/ru)
+
+Удачи!
diff --git a/ru-ru/ruby-ru.html.markdown b/ru-ru/ruby-ru.html.markdown
index 318e0e09..e69c6d94 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,21 +180,33 @@ 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
# Хэши -- это массив пар "ключ => значение".
# Хэши объявляются с использованием фигурных скобок:
hash = {'color' => 'green', 'number' => 5}
hash.keys #=> ['color', 'number']
+hash.values #=> ['green', 5]
# Значение в хэше легко может быть найдено по ключу:
hash['color'] #=> 'green'
@@ -173,17 +222,21 @@ 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
for counter in 1..5
@@ -219,7 +272,7 @@ end
#=> итерация 5
# Вы также можете ограничивать блоки фигурными скобками:
-(1..5).each {|counter| puts "итерация #{counter}"}
+(1..5).each { |counter| puts "итерация #{counter}" }
# Содержимое структурных данных также можно перебирать используя "each":
array.each do |element|
@@ -229,6 +282,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}"
@@ -240,22 +308,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 'Альтернативная система оценок, да?'
+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 "Альтернативная система оценок, да?"
+ puts 'Этот код будет выполнятся, если исключения не были вызваны'
+ensure
+ puts 'Этот код выполняется всегда'
end
+#=> Был вызван NoMemoryError
+#=> У вас закончилась память.
+#=> Этот код выполняется всегда
# Функции
@@ -297,6 +408,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
@@ -322,6 +470,13 @@ class Human
@name
end
+ # Тоже самое можно определить с помощью att_accessor
+ attr_accessor :name
+
+ # Также можно создать методы только для записи или чтения
+ attr_reader :name
+ attr_writer :name
+
# Метод класса определяется с ключевым словом "self",
# чтобы можно было отличить его от метода экземпляра класса.
# Он может быть вызван только на уровне класса, но не экземпляра.
diff --git a/ru-ru/swift-ru.html.markdown b/ru-ru/swift-ru.html.markdown
new file mode 100644
index 00000000..f2b1fd36
--- /dev/null
+++ b/ru-ru/swift-ru.html.markdown
@@ -0,0 +1,699 @@
+---
+language: swift
+contributors:
+ - ["Grant Timmerman", "http://github.com/grant"]
+ - ["Christopher Bess", "http://github.com/cbess"]
+ - ["Joey Huang", "http://github.com/kamidox"]
+ - ["Alexey Nazaroff", "http://github.com/rogaven"]
+filename: learnswift-ru.swift
+translators:
+ - ["Dmitry Bessonov", "https://github.com/TheDmitry"]
+ - ["Alexey Nazaroff", "https://github.com/rogaven"]
+lang: ru-ru
+---
+
+Swift - это язык программирования, созданный компанией Apple, для приложений
+под iOS и OS X. Разработанный, чтобы сосуществовать с Objective-C и
+быть более устойчивым к ошибочному коду, Swift был представлен в 2014 году на
+конференции разработчиков Apple, WWDC. Приложения на Swift собираются
+с помощью LLVM-компилятора, включенного в Xcode 6+.
+
+Официальная книга по [языку программирования Swift](https://itunes.apple.com/us/book/swift-programming-language/id881256329) от Apple доступна в iBooks.
+
+Смотрите еще [начальное руководство](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) Apple, которое содержит полное учебное пособие по Swift.
+
+```swift
+// Версия Swift: 3.0
+
+// импорт модуля
+import UIKit
+
+//
+// MARK: Основы
+//
+
+// Xcode поддерживает маркеры, чтобы давать примечания своему коду
+// и вносить их в список обозревателя (Jump Bar)
+// MARK: Метка раздела
+// MARK: - Метка с разделителем
+// TODO: Сделайте что-нибудь вскоре
+// FIXME: Исправьте этот код
+
+// Начиная со второй версии Swift, println и print объединены в методе print.
+// Перенос строки теперь добавляется в конец автоматически.
+print("Привет, мир!") // println – теперь просто print
+print("Привет, мир!", terminator: "") // вывод текста без переноса строки
+
+// переменные (var), значение которых можно изменить после инициализации
+// константы (let), значение которых нельзя изменить после инициализации
+
+var myVariable = 42
+let øπΩ = "значение" // именование переменной символами unicode
+let π = 3.1415926
+let convenience = "Ключевое слово" // контекстное имя переменной
+let weak = "Ключевое слово"; let override = "еще ключевое слово" // операторы
+ // могут быть отделены точкой с запятой
+let `class` = "Ключевое слово" // обратные апострофы позволяют использовать
+ // ключевые слова в именовании переменных
+let explicitDouble: Double = 70
+let intValue = 0007 // 7
+let largeIntValue = 77_000 // 77000
+let label = "некоторый текст " + String(myVariable) // Приведение типа
+let piText = "Pi = \(π), Pi 2 = \(π * 2)" // Вставка переменных в строку
+
+// Сборка особых значений
+// используя ключ -D сборки конфигурации
+#if false
+ print("Не печатается")
+ let buildValue = 3
+#else
+ let buildValue = 7
+#endif
+print("Значение сборки: \(buildValue)") // Значение сборки: 7
+
+/*
+ Опционалы - это особенность языка Swift, которая допускает вам сохранять
+ `некоторое` или `никакое` значения.
+
+ Язык Swift требует, чтобы каждое свойство имело значение, поэтому даже nil
+ должен быть явно сохранен как опциональное значение.
+
+ Optional<T> является перечислением.
+*/
+var someOptionalString: String? = "опционал" // Может быть nil
+// как и выше, только ? - это постфиксный оператор (синтаксический сахар)
+var someOptionalString2: Optional<String> = "опционал"
+
+if someOptionalString != nil {
+ // я не nil
+ if someOptionalString!.hasPrefix("opt") {
+ print("содержит префикс")
+ }
+
+ let empty = someOptionalString?.isEmpty
+}
+someOptionalString = nil
+
+/*
+Использование ! для доступа к несуществующему опциональному значению генерирует
+рантайм ошибку. Всегда проверяйте, что опционал содержит не пустое значение,
+перед тем как раскрывать его через !.
+*/
+
+// неявная развертка опциональной переменной
+var unwrappedString: String! = "Ожидаемое значение."
+// как и выше, только ! - постфиксный оператор (с еще одним синтаксическим сахаром)
+var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Ожидаемое значение."
+
+// If let конструкции -
+// If let это специальная конструкция в Swift, которая позволяет проверить Optional
+// справа от `=` непустой, и если это так - разворачивает его и присваивает левой части.
+if let someOptionalStringConstant = someOptionalString {
+ // имеется некоторое (`Some`) значение, не `nil`
+ if !someOptionalStringConstant.hasPrefix("ok") {
+ // нет такого префикса
+ }
+}
+
+// Swift поддерживает сохранение значения любого типа
+// Для этих целей есть два ключевых слова `Any` и `AnyObject`
+// AnyObject == id
+// `Any` же, в отличие от `id` в Objective-C, `Any` работает с любым значением (Class, Int, struct и т.д.)
+var anyVar: Any = 7
+anyVar = "Изменять значение на строку не является хорошей практикой, но возможно."
+let anyObjectVar: AnyObject = Int(1) as NSNumber
+
+/*
+ Комментируйте здесь
+
+ /*
+ Вложенные комментарии тоже поддерживаются
+ */
+*/
+
+//
+// MARK: Коллекции
+//
+
+/*
+ Массив (Array) и словарь (Dictionary) являются структурами (struct). Так
+ `let` и `var` также означают, что они изменяются (var) или не изменяются (let)
+ при объявлении переменных этих типов.
+*/
+
+// Массив
+var shoppingList = ["сом", "вода", "лимоны"]
+shoppingList[1] = "бутылка воды"
+let emptyArray = [String]() // let == неизменный
+let emptyArray2 = Array<String>() // как и выше
+var emptyMutableArray = [String]() // var == изменяемый
+var explicitEmptyMutableStringArray: [String] = [] // так же как и выше
+
+
+// Словарь
+var occupations = [
+ "Malcolm": "Капитан",
+ "kaylee": "Техник"
+]
+occupations["Jayne"] = "Связи с общественностью"
+let emptyDictionary = [String: Float]() // let == неизменный
+let emptyDictionary2 = Dictionary<String, Float>() // как и выше
+var emptyMutableDictionary = [String: Float]() // var == изменяемый
+var explicitEmptyMutableDictionary: [String: Float] = [:] // то же
+
+
+//
+// MARK: Поток управления
+//
+
+// С помощью "," можно указать дополнительные условия для раскрытия
+// опциональных значений.
+let someNumber = Optional<Int>(7)
+if let num = someNumber, num > 3 {
+ print("Больше 3х")
+}
+
+// цикл for для массива
+let myArray = [1, 1, 2, 3, 5]
+for value in myArray {
+ if value == 1 {
+ print("Один!")
+ } else {
+ print("Не один!")
+ }
+}
+
+// цикл for для словаря
+var dict = ["один": 1, "два": 2]
+for (key, value) in dict {
+ print("\(key): \(value)")
+}
+
+// цикл for для диапазона чисел
+for i in -1...shoppingList.count {
+ print(i)
+}
+shoppingList[1...2] = ["бифштекс", "орехи пекан"]
+// используйте ..< для исключения последнего числа
+
+// цикл while
+var i = 1
+while i < 1000 {
+ i *= 2
+}
+
+// цикл do-while
+repeat {
+ print("привет")
+} while 1 == 2
+
+// Переключатель
+// Очень мощный оператор, представляйте себе операторы `if` с синтаксическим
+// сахаром
+// Они поддерживают строки, объекты и примитивы (Int, Double, etc)
+let vegetable = "красный перец"
+switch vegetable {
+case "сельдерей":
+ let vegetableComment = "Добавьте немного изюма, имитируя муравьев на бревнышке."
+case "огурец", "кресс-салат":
+ let vegetableComment = "Было бы неплохо сделать бутерброд с чаем."
+case let localScopeValue where localScopeValue.hasSuffix("перец"):
+ let vegetableComment = "Это острый \(localScopeValue)?"
+default: // обязательный (чтобы предусмотреть все возможные вхождения)
+ let vegetableComment = "В супе все овощи вкусные."
+}
+
+
+//
+// MARK: Функции
+//
+
+// Функции являются типом первого класса, т.е. они могут быть вложены в функциях
+// и могут передаваться между собой
+
+// Функция с документированным заголовком Swift (формат Swift-модифицированный Markdown)
+
+/**
+ Операция приветствия
+
+ - Маркер в документировании
+ - Еще один маркер в документации
+
+ - Parameter name : Это имя
+ - Parameter day : Это день
+ - Returns : Строка, содержащая значения name и day.
+*/
+func greet(name: String, day: String) -> String {
+ return "Привет \(name), сегодня \(day)."
+}
+greet(name: "Боб", day: "вторник")
+
+// как и выше, кроме обращения параметров функции
+func greet2(name: String, externalParamName localParamName: String) -> String {
+ return "Привет \(name), сегодня \(localParamName)"
+}
+greet2(name: "Иван", externalParamName: "Воскресенье")
+
+// Функция, которая возвращает множество элементов в кортеже
+func getGasPrices() -> (Double, Double, Double) {
+ return (3.59, 3.69, 3.79)
+}
+let pricesTuple = getGasPrices()
+let price = pricesTuple.2 // 3.79
+// Пропускайте значения кортежей с помощью подчеркивания _
+let (_, price1, _) = pricesTuple // price1 == 3.69
+print(price1 == pricesTuple.1) // вывод: true
+print("Цена газа: \(price)")
+
+// Именованные параметры кортежа
+func getGasPrices2() -> (lowestPrice: Double, highestPrice: Double, midPrice: Double) {
+ return (1.77, 37.70, 7.37)
+}
+let pricesTuple2 = getGasPrices2()
+let price2 = pricesTuple2.lowestPrice
+let (_, price3, _) = pricesTuple2
+print(pricesTuple2.highestPrice == pricesTuple2.1) // вывод: true
+print("Самая высокая цена за газ: \(pricesTuple2.highestPrice)")
+
+// guard утверждения
+func testGuard() {
+ // guards обеспечивают прерывание дальнейшего выполнения функции,
+ // позволяя держать обработчики ошибок рядом с проверкой условия
+ // Объявляемая переменная находится в той же области видимости, что и guard.
+ guard let aNumber = Optional<Int>(7) else {
+ return
+ }
+
+ print("число равно \(aNumber)")
+}
+testGuard()
+
+// Переменное число аргументов
+func setup(numbers: Int...) {
+ // это массив
+ let number = numbers[0]
+ let argCount = numbers.count
+}
+
+// Передача и возврат функций
+func makeIncrementer() -> ((Int) -> Int) {
+ func addOne(number: Int) -> Int {
+ return 1 + number
+ }
+ return addOne
+}
+var increment = makeIncrementer()
+increment(7)
+
+// передача по ссылке
+func swapTwoInts(a: inout Int, b: inout Int) {
+ let tempA = a
+ a = b
+ b = tempA
+}
+var someIntA = 7
+var someIntB = 3
+swapTwoInts(a: &someIntA, b: &someIntB)
+print(someIntB) // 7
+
+
+//
+// MARK: Замыкания
+//
+var numbers = [1, 2, 6]
+
+// Функции - это частный случай замыканий ({})
+
+// Пример замыкания.
+// `->` отделяет аргументы и возвращаемый тип
+// `in` отделяет заголовок замыкания от тела замыкания
+numbers.map({
+ (number: Int) -> Int in
+ let result = 3 * number
+ return result
+})
+
+// Когда тип известен, как и выше, мы можем сделать так
+numbers = numbers.map({ number in 3 * number })
+// Или даже так
+//numbers = numbers.map({ $0 * 3 })
+
+print(numbers) // [3, 6, 18]
+
+// Хвостовое замыкание
+numbers = numbers.sorted { $0 > $1 }
+
+print(numbers) // [18, 6, 3]
+
+// Суперсокращение, поскольку оператор < выполняет логический вывод типов
+
+numbers = numbers.sorted(by: <)
+
+print(numbers) // [3, 6, 18]
+
+//
+// MARK: Структуры
+//
+
+// Структуры и классы имеют очень похожие характеристики
+struct NamesTable {
+ let names: [String]
+
+ // Пользовательский индекс
+ subscript(index: Int) -> String {
+ return names[index]
+ }
+}
+
+// У структур автогенерируемый (неявно) инициализатор
+let namesTable = NamesTable(names: ["Иван", "Яков"])
+let name = namesTable[1]
+print("Имя :\(name)") // Имя: Яков
+
+//
+// MARK: Обработка ошибок
+//
+
+// Протокол `Error` используется для перехвата выбрасываемых ошибок
+enum MyError: Error {
+ case badValue(msg: String)
+ case reallyBadValue(msg: String)
+}
+
+// фунции помеченные словом `throws` должны вызываться с помощью `try`
+func fakeFetch(value: Int) throws -> String {
+ guard 7 == value else {
+ throw MyError.reallyBadValue(msg: "Действительно плохое значение")
+ }
+
+ return "тест"
+}
+
+func testTryStuff() {
+ // предполагается, что не будет выброшено никаких ошибок,
+ // в противном случае мы получим рантайм исключение
+ let _ = try! fakeFetch(value: 7)
+
+ // Если возникает ошибка, то выполнение продолжится. Но если значение равно nil,
+ // то результат будет опционалом
+ let _ = try? fakeFetch(value: 7)
+
+ do {
+ // обычно try оператор, позволяющий обработать ошибку в `catch` блоке
+ try fakeFetch(value: 1)
+ } catch MyError.badValue(let msg) {
+ print("Ошибка: \(msg)")
+ } catch {
+ // все остальное
+ }
+}
+testTryStuff()
+
+//
+// MARK: Классы
+//
+
+// Классы, структуры и их члены имеют трехуровневый контроль доступа
+// Уровни: internal (по умолчанию), public, private
+
+public class Shape {
+ public func getArea() -> Int {
+ return 0
+ }
+}
+
+// Все методы и свойства класса являются открытыми (public).
+// Если вам необходимо содержать только данные
+// в структурированном объекте, вы должны использовать `struct`
+
+internal class Rect: Shape {
+ var sideLength: Int = 1
+
+ // Пользовательский сеттер и геттер
+ private var perimeter: Int {
+ get {
+ return 4 * sideLength
+ }
+ set {
+ // `newValue` - неявная переменная, доступная в сеттере
+ sideLength = newValue / 4
+ }
+ }
+
+ // Вычисляемые свойства должны быть объявлены с помощью `var`, ведь они могут меняться
+ var smallestSideLength: Int {
+ return self.sideLength - 1
+ }
+
+ // Ленивая загрузка свойства
+ // свойство subShape остается равным nil (неинициализированным),
+ // пока не вызовется геттер
+ lazy var subShape = Rect(sideLength: 4)
+
+ // Если вам не нужны пользовательские геттеры и сеттеры,
+ // но все же хотите запустить код перед и после вызовов геттера или сеттера
+ // свойств, вы можете использовать `willSet` и `didSet`
+ var identifier: String = "defaultID" {
+ // аргумент у `willSet` будет именем переменной для нового значения
+ willSet(someIdentifier) {
+ print(someIdentifier)
+ }
+ }
+
+ init(sideLength: Int) {
+ self.sideLength = sideLength
+ // последним всегда вызывается super.init, когда init с параметрами
+ super.init()
+ }
+
+ func shrink() {
+ if sideLength > 0 {
+ sideLength -= 1
+ }
+ }
+
+ override func getArea() -> Int {
+ return sideLength * sideLength
+ }
+}
+
+// Простой класс `Square` наследует `Rect`
+class Square: Rect {
+ convenience init() {
+ self.init(sideLength: 5)
+ }
+}
+
+var mySquare = Square()
+print(mySquare.getArea()) // 25
+mySquare.shrink()
+print(mySquare.sideLength) // 4
+
+// преобразование объектов
+let aShape = mySquare as Shape
+
+// сравнение экземпляров, в отличие от ==, которая проверяет эквивалентность
+if mySquare === mySquare {
+ print("Ага, это mySquare")
+}
+
+// Опциональная инициализация (init)
+class Circle: Shape {
+ var radius: Int
+ override func getArea() -> Int {
+ return 3 * radius * radius
+ }
+
+ // Поместите постфиксный знак вопроса после `init` - это и будет опциональная инициализация,
+ // которая может вернуть nil
+ init?(radius: Int) {
+ self.radius = radius
+ super.init()
+
+ if radius <= 0 {
+ return nil
+ }
+ }
+}
+
+var myCircle = Circle(radius: 1)
+print(myCircle?.getArea()) // Optional(3)
+print(myCircle!.getArea()) // 3
+var myEmptyCircle = Circle(radius: -1)
+print(myEmptyCircle?.getArea()) // "nil"
+if let circle = myEmptyCircle {
+ // не будет выполняться, поскольку myEmptyCircle равен nil
+ print("circle не nil")
+}
+
+
+//
+// MARK: Перечисления
+//
+
+// Перечисления могут быть определенного или своего типа.
+// Они могут содержать методы подобно классам.
+
+enum Suit {
+ case spades, hearts, diamonds, clubs
+ func getIcon() -> String {
+ switch self {
+ case .spades: return "♤"
+ case .hearts: return "♡"
+ case .diamonds: return "♢"
+ case .clubs: return "♧"
+ }
+ }
+}
+
+// Значения перечислений допускают сокращенный синтаксис, нет необходимости
+// указывать тип перечисления, когда переменная объявляется явно
+var suitValue: Suit = .hearts
+
+// Значения нецелочисленных перечислений должны быть указаны явно
+// или могут выводится с помощью функции `rawValue` из имени
+enum BookName: String {
+ case john
+ case luke = "Лука"
+}
+print("Имя: \(BookName.john.rawValue)")
+
+// Перечисление (enum) со связанными значениями
+enum Furniture {
+ // Связать с типом Int
+ case desk(height: Int)
+ // Связать с типами String и Int
+ case chair(String, Int)
+
+ func description() -> String {
+ switch self {
+ case .desk(let height):
+ return "Письменный стол высотой \(height) см."
+ case .chair(let brand, let height):
+ return "Стул марки \(brand) высотой \(height) см."
+ }
+ }
+}
+
+var desk: Furniture = .desk(height: 80)
+print(desk.description()) // "Письменный стол высотой 80 см."
+var chair = Furniture.chair("Foo", 40)
+print(chair.description()) // "Стул марки Foo высотой 40 см."
+
+
+//
+// MARK: Протоколы
+//
+
+// `protocol` может потребовать, чтобы у соответствующих типов
+// были определенные свойства экземпляра, методы экземпляра, тип методов,
+// операторы и индексы.
+
+protocol ShapeGenerator {
+ var enabled: Bool { get set }
+ func buildShape() -> Shape
+}
+
+// Протоколы, объявленные с @objc, допускают необязательные функции,
+// которые позволяют вам проверять на соответствие. Для функций также необходимо указать @objc
+@objc protocol TransformShape {
+ @objc optional func reshape()
+ @objc optional func canReshape() -> Bool
+}
+
+class MyShape: Rect {
+ var delegate: TransformShape?
+
+ func grow() {
+ sideLength += 2
+
+ // Размещайте знак вопроса перед опционным свойством, методом
+ // или индексом, чтобы не учитывать nil-значение и возвратить nil
+ // вместо выбрасывания ошибки выполнения (т.н. "опционная цепочка")
+ if let reshape = self.delegate?.canReshape?(), reshape {
+ // проверка делегата на выполнение метода
+ self.delegate?.reshape?()
+ }
+ }
+}
+
+
+//
+// MARK: Прочее
+//
+
+// `extension`s: Добавляет расширенный функционал к существующему типу
+
+// Класс Square теперь "соответствует" протоколу `CustomStringConvertible`
+extension Square: CustomStringConvertible {
+ var description: String {
+ return "Площадь: \(self.getArea()) - ID: \(self.identifier)"
+ }
+}
+
+print("Объект Square: \(mySquare)")
+
+// Вы также можете расширить встроенные типы
+extension Int {
+ var customProperty: String {
+ return "Это \(self)"
+ }
+
+ func multiplyBy(num: Int) -> Int {
+ return num * self
+ }
+}
+
+print(7.customProperty) // "Это 7"
+print(14.multiplyBy(num: 3)) // 42
+
+// Обобщения: Подобно языкам Java и C#. Используйте ключевое слово `where`,
+// чтобы определить условия обобщений.
+
+func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
+ for (index, value) in array.enumerated() {
+ if value == valueToFind {
+ return index
+ }
+ }
+ return nil
+}
+let foundAtIndex = findIndex(array: [1, 2, 3, 4], valueToFind: 3)
+print(foundAtIndex == 2) // вывод: true
+
+// Операторы:
+// Пользовательские операторы могут начинаться с символов:
+// / = - + * % < > ! & | ^ . ~
+// или
+// Unicode- знаков математики, символов, стрелок, декорации и линий/кубов,
+// нарисованных символов.
+prefix operator !!!
+
+// Префиксный оператор, который утраивает длину стороны, когда используется
+prefix func !!! (shape: inout Square) -> Square {
+ shape.sideLength *= 3
+ return shape
+}
+
+// текущее значение
+print(mySquare.sideLength) // 4
+
+// Используя пользовательский оператор !!!, изменится длина стороны
+// путем увеличения размера в 3 раза
+!!!mySquare
+print(mySquare.sideLength) // 12
+
+// Операторы также могут быть обобщенными
+infix operator <->
+func <-><T: Equatable> (a: inout T, b: inout T) {
+ let c = a
+ a = b
+ b = c
+}
+
+var foo: Float = 10
+var bar: Float = 20
+
+foo <-> bar
+print("foo это \(foo), bar это \(bar)") // "foo = 20.0, bar = 10.0"
+```
diff --git a/ru-ru/tmux-ru.html.markdown b/ru-ru/tmux-ru.html.markdown
new file mode 100644
index 00000000..aa7545cc
--- /dev/null
+++ b/ru-ru/tmux-ru.html.markdown
@@ -0,0 +1,252 @@
+---
+category: tool
+tool: tmux
+contributors:
+ - ["mdln", "https://github.com/mdln"]
+translators:
+ - ["Davydov Anton", "https://github.com/davydovanton"]
+filename: LearnTmux-ru.txt
+lang: ru-ru
+---
+
+[tmux](http://tmux.sourceforge.net) - терминальный мультиплексор.
+Он позволяет создавать, получать доступ и контролировать любое
+количество терминалов из единого окна.
+Сессия tmux также может быть свернута в фоновый режим, и она
+будет работать в фоне, а после к ней можно будет подключиться.
+
+
+```
+
+ tmux [command] # Запуск команды 'tmux'
+ # без какой-либо команды создаст новую сессию
+
+ new # Создать новую сессию
+ -s "Session" # Создать именованную сессию
+ -n "Window" # Создать именованное окно
+ -c "/dir" # Запустить сессию в конкретной директории
+
+ attach # Подключиться к последней/существующей сессии
+ -t "№" # Подключиться к определенной сессии
+ -d # Завершить определенную сессию
+
+ ls # Список открытых сессий
+ -a # Список всех открытых сессий
+
+ lsw # Список окон
+ -a # Список всех окон
+ -s # Список всех окон в сессии
+
+ lsp # Список панелей
+ -a # Список всех панелей
+ -s # Список всех панелей в сессии
+ -t # Список всех панелей для конкретного объекта
+
+ kill-window # Закрыть текущее окно
+ -t "#" # Закрыть конкретное окно
+ -a # Закрыть все окна
+ -a -t "#" # Закрыть все окна, кроме конкретного
+
+ kill-session # Завершить текущую сессию
+ -t "#" # Завершить конкретную сессию
+ -a # Завершить все сессии
+ -a -t "#" # Завершить все сессии, кроме конкретной
+
+```
+
+
+### "Горячие" клавиши
+
+Способ, с помощью которого контролируется любая tmux
+сессия, - комбинация клавиш, называемая 'Префиксом'.
+
+```
+----------------------------------------------------------------------
+ (C-b) = Ctrl + b # 'Префикс' необходим для
+ # использования горячих клавиш
+
+ (M-1) = Meta + 1 -или- Alt + 1
+----------------------------------------------------------------------
+
+ ? # Список всех горячих клавиш
+ : # Начать ввод в командной строке tmux
+ r # Принудительная перерисовка текущего клиента
+ c # Создать новое окно
+
+ ! # Переместить текущую панель в отдельное окно
+ % # Разделить текущую панель на две: левую и правую
+ " # Разделить текущую панель на две: верхнюю и нижнюю
+
+ n # Переместиться на следующее окно
+ p # Переместиться на предыдущее окно
+ { # Заменить текущую панель на предыдущую
+ } # Заменить текущую панель на следующую
+
+ s # Интерактивный выбор запущенных сессий
+ w # Интерактивный выбор текущего окна
+ от 0 до 9 # Выбрать окно номер 0..9
+
+ d # Отключить текущий клиент
+ D # Выбрать клиент, который будет отключен
+
+ & # Закрыть текущее окно
+ x # Закрыть текущую панель
+
+ Стрелки вверх, вниз # Переместиться на панель выше, ниже, левее
+ влево, вправо # или правее
+
+ M-1 to M-5 # Расставить панели:
+ # 1) выровнять по горизонтали
+ # 2) выровнять по вертикали
+ # 3) основное горизонтально
+ # 4) основное вертикально
+ # 5) мозаикой
+
+ C-Up, C-Down # Изменение размера текущей панели с шагом в одну
+ C-Left, C-Right # колонку
+
+ M-Up, M-Down # Изменение размера текущей панели с шагом в пять
+ M-Left, M-Right # колонок
+
+```
+
+
+### Настройка ~/.tmux.conf
+
+Файл tmux.conf может быть использован для автоматической установки
+опций при старте, как, например, .vimrc или init.el.
+
+```
+# Пример файла tmux.conf
+# 2014.10
+
+
+### Общее
+###########################################################################
+
+# Включить поддержку UTF-8
+setw -g utf8 on
+set-option -g status-utf8 on
+
+# Установить лимит истории
+set -g history-limit 2048
+
+# Порядковый номер первой панели
+set -g base-index 1
+
+# Включить поддержку мыши
+set-option -g mouse-select-pane on
+
+# Принудительная перезагрузка конфигурационного файла
+unbind r
+bind r source-file ~/.tmux.conf
+
+
+### Горячие клавиши
+###########################################################################
+
+# Отменить комбинацию C-b как стандартный префикс
+unbind C-b
+
+# Установить новую комбинацию как префикс
+set-option -g prefix `
+
+# Вернуть предыдущее окно, если префикс был нажат два раза
+bind C-a last-window
+bind ` last-window
+
+# Разрешить замену C-a и ` на F11/F12
+bind F11 set-option -g prefix C-a
+bind F12 set-option -g prefix `
+
+# Настройки клавиш
+setw -g mode-keys vi
+set-option -g status-keys vi
+
+# Перемещение между панелями, как в vim
+bind h select-pane -L
+bind j select-pane -D
+bind k select-pane -U
+bind l select-pane -R
+
+# Переключить/Заменить окно
+bind e previous-window
+bind f next-window
+bind E swap-window -t -1
+bind F swap-window -t +1
+
+# Комманды, упрощающие разделением панелей
+bind = split-window -h
+bind - split-window -v
+unbind '"'
+unbind %
+
+# Активировать центральную сессию (когда вложенный tmux) для отправки команд
+bind a send-prefix
+
+
+### Цветовая схема
+###########################################################################
+
+# Цветовая палитра строки состояния
+set-option -g status-justify left
+set-option -g status-bg black
+set-option -g status-fg white
+set-option -g status-left-length 40
+set-option -g status-right-length 80
+
+# Цветовая палитра окантовки панели
+set-option -g pane-active-border-fg green
+set-option -g pane-active-border-bg black
+set-option -g pane-border-fg white
+set-option -g pane-border-bg black
+
+# Цветовая палитра сообщений
+set-option -g message-fg black
+set-option -g message-bg green
+
+# Цветовая палитра статус окна
+setw -g window-status-bg black
+setw -g window-status-current-fg green
+setw -g window-status-bell-attr default
+setw -g window-status-bell-fg red
+setw -g window-status-content-attr default
+setw -g window-status-content-fg yellow
+setw -g window-status-activity-attr default
+setw -g window-status-activity-fg yellow
+
+
+### Интерфейс
+###########################################################################
+
+# Уведомления
+setw -g monitor-activity on
+set -g visual-activity on
+set-option -g bell-action any
+set-option -g visual-bell off
+
+# Автоматическая установка заголовка окна
+set-option -g set-titles on
+set-option -g set-titles-string '#H:#S.#I.#P #W #T' # window number,program name,active (or not)
+
+# Настройки строки состояния
+set -g status-left "#[fg=red] #H#[fg=green]:#[fg=white]#S#[fg=green] |#[default]"
+
+# Показывать системные характеристики в статусбаре
+# Требует https://github.com/thewtex/tmux-mem-cpu-load/
+set -g status-interval 4
+set -g status-right "#[fg=green] | #[fg=white]#(tmux-mem-cpu-load)#[fg=green] | #[fg=cyan]%H:%M #[default]"
+
+```
+
+### Ссылки
+
+[Tmux | Домашняя страница](http://tmux.sourceforge.net)
+
+[Страница мануала Tmux](http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/tmux.1?query=tmux)
+
+[Gentoo Wiki](http://wiki.gentoo.org/wiki/Tmux)
+
+[Archlinux Wiki](https://wiki.archlinux.org/index.php/Tmux)
+
+[Отображение CPU/MEM % в статусбаре](https://stackoverflow.com/questions/11558907/is-there-a-better-way-to-display-cpu-usage-in-tmux)
diff --git a/ru-ru/typescript-ru.html.markdown b/ru-ru/typescript-ru.html.markdown
new file mode 100644
index 00000000..09bbb2d1
--- /dev/null
+++ b/ru-ru/typescript-ru.html.markdown
@@ -0,0 +1,173 @@
+---
+language: TypeScript
+lang: ru-ru
+contributors:
+ - ["Philippe Vlérick", "https://github.com/pvlerick"]
+translators:
+ - ["Fadil Mamedov", "https://github.com/fadilmamedov"]
+ - ["Andre Polykanine", "https://github.com/Oire"]
+filename: learntypescript-ru.ts
+---
+
+TypeScript — это язык программирования, целью которого является лёгкая разработка широкомасштабируемых JavaScript-приложений.
+TypeScript добавляет в Javascript общие концепции, такие, как классы, модули, интерфейсы, обобщённое программирование и (опционально) статическую типизацию.
+Это надмножество языка JavaScript: весь JavaScript-код является валидным TypeScript-кодом, следовательно, может быть добавлен бесшовно в любой проект.
+Компилятор TypeScript генерирует JavaScript-код.
+
+Эта статья концентрируется только на синтаксисе TypeScript, в противовес статье о [JavaScript](javascript-ru/).
+
+Для тестирования компилятора TypeScript пройдите по ссылке в [песочницу](http://www.typescriptlang.org/Playground).
+Там вы можете написать код (с поддержкой автодополнения) и сразу же увидеть сгенерированный JavaScript код.
+
+```js
+// В TypeScript есть 3 базовых типа
+var isDone: boolean = false;
+var lines: number = 42;
+var name: string = "Андерс";
+
+// Тип «any» для случаев, когда заранее неизвестен тип переменной
+var notSure: any = 4;
+notSure = "а может быть, строка";
+notSure = false; // а теперь логический тип
+
+// Для коллекций есть типизированные массивы и обобщённые массивы
+var list: number[] = [1, 2, 3];
+// Как альтернатива, использование обобщённого массива
+var list: Array<number> = [1, 2, 3];
+
+// Перечисления:
+enum Color {Red, Green, Blue};
+var c: Color = Color.Green;
+
+// Наконец, «void» используется для обозначения того, что функция ничего не возвращает
+function bigHorribleAlert(): void {
+ alert("Я маленькое надоедливое окошко!");
+}
+
+// Функции — это объекты первого класса. Они поддерживают лямбда-синтаксис (=>)
+// и используют вывод типов (type inference)
+
+// Следующие строки кода являются эквивалентными, компилятором предполагается
+// одинаковая сигнатура, на выходе генерируется одинаковый JavaScript-код
+var f1 = function(i: number): number { return i * i; }
+// Предполагается возвращаемый тип
+var f2 = function(i: number) { return i * i; }
+var f3 = (i: number): number => { return i * i; }
+// Предполагается возвращаемый тип
+var f4 = (i: number) => { return i * i; }
+// Предполагается возвращаемый тип, в однострочной функции ключевое слово «return» не нужно
+var f5 = (i: number) => i * i;
+
+// Интерфейсы являются структурными; всё, что имеет свойства, совместимо с интерфейсом
+interface Person {
+ name: string;
+ // Опциональные свойства, помеченные символом «?»
+ age?: number;
+ // И, конечно, функции
+ move(): void;
+}
+
+// Объект, который реализует интерфейс «Person»
+// К нему можно обращаться, как к «Person», так как он имеет свойства «name» и «move»
+var p: Person = { name: "Бобби", move: () => {} };
+// Объекты, которые могут иметь опциональные свойства:
+var validPerson: Person = { name: "Бобби", age: 42, move: () => {} };
+// Это не «Person», поскольку «age» не является числовым значением
+var invalidPerson: Person = { name: "Бобби", age: true };
+
+// Интерфейсы могут также описывать функциональный тип
+interface SearchFunc {
+ (source: string, subString: string): boolean;
+}
+// Важны только типы параметров, имена — нет.
+var mySearch: SearchFunc;
+mySearch = function(src: string, sub: string) {
+ return src.search(sub) != -1;
+}
+
+// Классы. Члены класса по умолчанию являются публичными
+class Point {
+ // Свойства
+ x: number;
+
+ // Конструктор — ключевые слова public/private в данном контексте сгенерируют
+ // шаблонный код для свойства и для инициализации в конструкторе
+ // В данном примере «y» будет определён так же, как и «x», но меньшим количеством кода
+ // Значения по умолчанию также поддерживаются
+
+ constructor(x: number, public y: number = 0) {
+ this.x = x;
+ }
+
+ // Функции
+ dist() { return Math.sqrt(this.x * this.x + this.y * this.y); }
+
+ // Статические члены
+ static origin = new Point(0, 0);
+}
+
+var p1 = new Point(10 ,20);
+var p2 = new Point(25); //y будет равен 0
+
+// Наследование
+class Point3D extends Point {
+ constructor(x: number, y: number, public z: number = 0) {
+ super(x, y); // Явный вызов конструктора базового класса обязателен
+ }
+
+ // Перегрузка
+ dist() {
+ var d = super.dist();
+ return Math.sqrt(d * d + this.z * this.z);
+ }
+}
+
+// Модули, знак «.» может быть использован как разделитель для обозначения подмодулей
+module Geometry {
+ export class Square {
+ constructor(public sideLength: number = 0) {
+ }
+ area() {
+ return Math.pow(this.sideLength, 2);
+ }
+ }
+}
+
+var s1 = new Geometry.Square(5);
+
+// Локальный псевдоним для ссылки на модуль
+import G = Geometry;
+
+var s2 = new G.Square(10);
+
+// Обобщённое программирование
+// Классы
+class Tuple<T1, T2> {
+ constructor(public item1: T1, public item2: T2) {
+ }
+}
+
+// Интерфейсы
+interface Pair<T> {
+ item1: T;
+ item2: T;
+}
+
+// И функции
+var pairToTuple = function<T>(p: Pair<T>) {
+ return new Tuple(p.item1, p.item2);
+};
+
+var tuple = pairToTuple({ item1:"hello", item2:"world"});
+
+// Включение ссылки на файл определения:
+/// <reference path="jquery.d.ts" />
+
+```
+
+## Для дальнейшего чтения
+ * [Официальный веб-сайт TypeScript](http://www.typescriptlang.org/)
+ * [Спецификация языка TypeScript (pdf)](http://go.microsoft.com/fwlink/?LinkId=267238)
+ * [Anders Hejlsberg — Introducing TypeScript на Channel 9](http://channel9.msdn.com/posts/Anders-Hejlsberg-Introducing-TypeScript)
+ * [Исходный код на GitHub](https://github.com/Microsoft/TypeScript)
+ * [Definitely Typed — репозиторий определений типов](http://definitelytyped.org/)
diff --git a/ru-ru/vim-ru.html.markdown b/ru-ru/vim-ru.html.markdown
new file mode 100644
index 00000000..f43f99eb
--- /dev/null
+++ b/ru-ru/vim-ru.html.markdown
@@ -0,0 +1,241 @@
+---
+category: tool
+tool: vim
+contributors:
+ - ["RadhikaG", "https://github.com/RadhikaG"]
+translators:
+ - ["Anton Slukovskiy", "https://github.com/slukovskiy"]
+filename: LearnVim-ru.txt
+lang: ru-ru
+---
+
+[Vim](http://www.vim.org)
+(Vi IMproved) это клон полулярного текстового редактора для Unix. Он разработан
+с целью повышения скорости и продуктивности и повсеместно используется в
+большинство Юникс-подобных систем. В нем имеется множество клавиатурных
+сочетаний для быстрой навигации к определенным точкам в файле и быстрого
+редактирования.
+
+## Основы навигации в vim
+
+```
+ vim <filename> # Открыть <filename> в vim
+ :q # Выйти из vim
+ :w # Сохранить текущий файл
+ :wq # Сохранить и выйти
+ :q! # Выйти из vim не сохраняя файл
+
+ :x # Сохранить файл и выйти из vim, короткая версия :wq
+
+ u # Отмена последней команды
+ CTRL+R # Отмена отмены
+
+ h # Переместить курсор на один символ влево
+ j # Переместить курсор на один символ вниз
+ k # Переместить курсор на один символ вверх
+ l # Переместить курсор на один символ вправо
+
+ # Перемещение по строке
+
+ 0 # Переместить курсор к началу строки
+ $ # Переместить курсор к концу строки
+ ^ # Переместить курсор к первому непустому символу в строке
+
+ # Поиск в тексте
+
+ /<word> # Подсветить все вхождения <word> в тексте после курсора
+ ?<word> # Подсветить все вхождения <word> в тексте до курсора
+ n # Передвигает курсор к следующему вхождения искомого слова
+ N # Передвигает курсор к предыдущему вхождения искомого слова
+
+ :%s/foo/bar/g # Меняет «foo» на «bar» во всем файле
+ :s/foo/bar/g # Меняет «foo» на «bar» на текущей строке
+
+ # Переходы к символу
+
+ f<character> # Перенести курсор к <character>
+ t<character> # Перенести курсор вперед и остановиться прямо
+ # перед <character>
+
+ # Например,
+ f< # Перести курсор и остановиться на <
+ t< # Перенсти курсор и остановиться прямо перед <
+
+ # Перемещение по словам
+
+ w # Переместиться вперед на одно слово
+ b # Перенеститься назад на одно слово
+ e # Перейти к концу текущего слова
+
+ # Другие команды для передвижения по тексту
+
+ gg # Перейти к началу файла
+ G # Перейти к концу файла
+ :NUM # Перейти к строке под номером NUM
+ # (NUM может быть любым числом)
+ H # Переместить курсор к верхнему краю экрана
+ M # Переместить курсор к середине экрана
+ L # Переместить курсор к нижнему краю экрана
+```
+
+## Режимы:
+
+Vim основывается на концепте **режимов**.
+
+Командный режим - vim запускается в этом режиме по-умолчанию, используется для
+навигации и ввода команд.
+Режим ввода - используется для внесения изменений в файле.
+Визуальный режим - используется для подсветки текста и выполнения операций над ним.
+Режим командной строки - используется для ввода команд в нижнем углу экрана после символа «:».
+
+```
+ i # Переводит vim в режим вставки перед позицией курсора
+ a # Переводит vim в режим вставки после позиции курсора
+ v # Переводит vim в визуальный режим
+ : # Переводит vim в режим командной строки
+ <esc> # Выходит из любого режима в котором вы находитесь
+ # в командный режим
+
+ # Копирование и вставка текста
+
+ y # Скопировать выделенное
+ yy # Скопировать текущую строку
+ d # Удалить выделенное
+ dd # Удалить текущую строку
+ p # Вставить скопированный текст после текущей позиции курсора
+ P # Вставить скопированный текст перед текущей позицией курсора
+ x # Удалить символ под текущей позицией курсора
+```
+
+## «Грамматика» vim
+
+Vim можно рассматривать как набор команд в формате «Глагол-Модификатор-Существительное», где:
+
+Глагол - ваше действие.
+Модификатор - то как вы его выполняете.
+Существительное - объект над которым вы его выполняете.
+
+Несколько важных пример «Глаголов», «Модификаторов», и «Существительных»:
+
+```
+ # «Глаголы»
+
+ d # Удалить
+ c # Изменить
+ y # Скопировать
+ v # Визуально выделить
+
+ # «Модификаторы»
+
+ i # Внутри
+ a # Снаружи
+ NUM # Число
+ f # Ищет что-то и останавливается на нем
+ t # Ищет что-то и останавливается перед ним
+ / # Ищет строку после курсора
+ ? # Ищет строку перед курсором
+
+ # «Существительные»
+
+ w # Слово
+ s # Предложение
+ p # Параграф
+ b # Блок
+
+ # Образцы «предложений» или команд
+
+ d2w # Удалить 2 слова
+ cis # Изменить объемлющее предложение
+ yip # Скопировать объемлющий параграф
+ ct< # Изменяет текст от курсора до следующей открывающей скобки
+ d$ # Удалить все от положения курсора до конца строки
+```
+
+## Некоторые сокращения и хитрости
+
+ <!--TODO: Add more!-->
+```
+ > # Сдвинуть выделенное на один отступ вправо
+ < # Сдвинуть выделенное на один отступ влево
+ :earlier 15m # Возвращает документ к состоянию в котором он был
+ # 15 минут назад
+ :later 15m # Отменяет предыдущую команду
+ ddp # Меняет позиции последовательных строк, сначала dd затем p
+ . # Повторяет предыдущее действие
+```
+
+## Макросы
+
+Макросы это просто записываемые действия.
+Во время записи макросы запоминают **все** действия и команды до тех пор пока
+запись не будет остановлена.При вызове макрос применяет ту же самую последовательность
+действий и команд на выделенном тексте.
+
+```
+ qa # Начать запись макроса под именем «a»
+ q # Закончить запись
+ @a # Выполнить макрос
+```
+
+### Настройка ~/.vimrc
+
+Файл .vimrc может использоваться для настройки Vim при запуске.
+
+Вот пример файла ~/.vimrc:
+
+```
+" Пример ~/.vimrc
+" 2015.10
+
+" Отключает совместимость со старым vi
+set nocompatible
+
+" Определяет тип файла по его имени для разрешения автоматических отступов и т. д.
+filetype indent plugin on
+
+" Включает подсветку синтаксиса
+syntax on
+
+" Улучшенное автодополнение команд
+set wildmenu
+
+" Использовать поиск не чувствительный к регистру
+" за исключением использования заглавный букв
+set ignorecase
+set smartcase
+
+" Копирует отступы с текущей строки при добавлении новой
+set autoindent
+
+" Показывать номера строк
+set number
+
+" Настройки отступов, изменяйте по собственному вкусу
+
+" Количество видимых пробелов на один символ табуляции
+set tabstop=4
+
+" Количество пробелов в символе табуляции при редактировании
+set softtabstop=4
+
+" Количество пробелов в отступе при использовании операций >> и <<
+set shiftwidth=4
+
+" Конвертировать символы табуляции в пробелы
+set expandtab
+
+" Включить умную табуляцию и пробелы для отступов и выравнивания
+set smarttab
+```
+
+### Ссылки
+
+[Vim | Home (EN)](http://www.vim.org/index.php)
+
+`$ vimtutor`
+
+[A vim Tutorial and Primer (EN)](https://danielmiessler.com/study/vim/)
+
+[What are the dark corners of Vim your mom never told you about? (Stack Overflow thread) (EN)](http://stackoverflow.com/questions/726894/what-are-the-dark-corners-of-vim-your-mom-never-told-you-about)
+
+[Arch Linux Wiki](https://wiki.archlinux.org/index.php/Vim_%28%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9%29)
diff --git a/ru-ru/xml-ru.html.markdown b/ru-ru/xml-ru.html.markdown
new file mode 100644
index 00000000..bf3f22b0
--- /dev/null
+++ b/ru-ru/xml-ru.html.markdown
@@ -0,0 +1,145 @@
+---
+language: xml
+filename: learnxml-ru.xml
+contributors:
+ - ["João Farias", "https://github.com/JoaoGFarias"]
+translators:
+ - ["Dmitry Bessonov", "https://github.com/TheDmitry"]
+lang: ru-ru
+---
+
+XML - это язык разметки, предназначенный для хранения и передачи данных.
+
+В отличие от HTML, XML не определяет, как отображать или форматировать данные, он только содержит их.
+
+* XML-Синтаксис
+
+```xml
+<!-- Комментарии в XML выглядят вот так -->
+
+<?xml version="1.0" encoding="UTF-8"?>
+<bookstore>
+ <book category="КУЛИНАРИЯ">
+ <title lang="ru">Итальянская кухня каждый день</title>
+ <author>Giada De Laurentiis</author>
+ <year>2005</year>
+ <price>30.00</price>
+ </book>
+ <book category="ДЕТИ">
+ <title lang="ru">Гарри Поттер</title>
+ <author>Дж. К. Роулинг</author>
+ <year>2005</year>
+ <price>29.99</price>
+ </book>
+ <book category="ВСЕМИРНАЯ ПАУТИНА">
+ <title lang="ru">Изучаем XML</title>
+ <author>Эрик Рэй</author>
+ <year>2003</year>
+ <price>39.95</price>
+ </book>
+</bookstore>
+
+<!-- Вышеописанный документ - типичный XML-файл.
+ Он начинается с определения, объявляющего о некоторых метаданных (необязательно).
+
+ XML использует древовидную структуру. У вышеописанного документа
+ корневой узел - 'bookstore', который содержит три дочерних узла - все 'book'-узлы.
+ Такие узлы содержат еще дочерние узлы и т.д.
+
+ Узлы создаются с помощью открывающих/закрывающих тегов,
+ а дочерние узлы - это узлы между открывающимися и закрывающимися тегами.-->
+
+
+<!-- XML содержит в себе два типа данных:
+ 1 - Атрибуты -> Это метаданные узлов.
+ Обычно XML-парсер использует эту информацию, чтобы хранить свойства данных.
+ Атрибут изображается путем вписывания его в скобки в пределах открытого тега
+ 2 - Элементы -> Это чистые данные.
+ Это то, что парсер извлечет из XML-файла.
+ Элементы идут между открытыми и закрытыми тегами без скобок. -->
+
+
+<!-- Ниже элемент с двумя атрибутами -->
+<file type="gif" id="4293">компьютер.gif</file>
+
+
+```
+
+* Хорошо отформатированный документ x Проверка достоверности
+
+XML-документ хорошо отформатирован, если он синтаксически верный.
+Впрочем, в документ возможно ввести больше ограничений,
+используя определения документа, вроде DTD и XML-схемы.
+
+XML-документ, который следует описанию документа, называется корректным,
+относительно этого документа.
+
+С таким инструментом вы можете проверить XML-данные вне логики приложения.
+
+```xml
+
+<!-- Ниже вы можете увидеть упрощенную версию документа книжного магазина,
+ с дополнением DTD-определения.-->
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE note SYSTEM "Bookstore.dtd">
+<bookstore>
+ <book category="КУЛИНАРИЯ">
+ <title >Итальянская кухня каждый день</title>
+ <price>30.00</price>
+ </book>
+</bookstore>
+
+<!-- Этот DTD может быть чем-то вроде:-->
+
+<!DOCTYPE note
+[
+<!ELEMENT bookstore (book+)>
+<!ELEMENT book (title,price)>
+<!ATTLIST book category CDATA "Литература">
+<!ELEMENT title (#PCDATA)>
+<!ELEMENT price (#PCDATA)>
+]>
+
+
+<!-- DTD начинается с объявления.
+ Затем объявляется корневой узел, требующий 1 или более дочерних узлов 'book'.
+ Каждый 'book' должен содержать точно один 'title' и 'price', и атрибут,
+ называемый 'category', со значением "Литература" по умолчанию.
+ Узлы 'title' и 'price' содержат анализируемые символьные данные.-->
+
+<!-- DTD может быть объявлен в самом XML-файле.-->
+
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE note
+[
+<!ELEMENT bookstore (book+)>
+<!ELEMENT book (title,price)>
+<!ATTLIST book category CDATA "Литература">
+<!ELEMENT title (#PCDATA)>
+<!ELEMENT price (#PCDATA)>
+]>
+
+<bookstore>
+ <book category="КУЛИНАРИЯ">
+ <title >Итальянская кухня каждый день</title>
+ <price>30.00</price>
+ </book>
+</bookstore>
+```
+
+## DTD совместимость и определение XML Schema(схем/структуры)
+
+Поддержка DTDs является повсеместным, потому что это довольно старая технология. К сожалению, современные функции XML как пространств имен(namespaces) не поддерживаются DTDs. Определения XML-схемы (XSDs) предназначены для замены DTDs которая в свою очередь предназначена для определения грамматики XML-документа.
+
+## Ресурсы
+
+* [Валидатор XML (ссылка на английском языке)](http://www.xmlvalidation.com)
+
+## Для будущего прочтения
+
+* [XML Schema Definitions Tutorial (ссылка на английском языке)](http://www.w3schools.com/schema/)
+* [DTD руководство (ссылка на английском языке)](http://www.w3schools.com/xml/xml_dtd_intro.asp)
+* [XML руководство (ссылка на английском языке)](http://www.w3schools.com/xml/default.asp)
+* [использование XPath запросов для парсинга XML (ссылка на английском языке)](http://www.w3schools.com/xml/xml_xpath.asp)