summaryrefslogtreecommitdiffhomepage
path: root/ru-ru
diff options
context:
space:
mode:
Diffstat (limited to 'ru-ru')
-rw-r--r--ru-ru/c-ru.html.markdown4
-rw-r--r--ru-ru/go-ru.html.markdown174
-rw-r--r--ru-ru/haskell-ru.html.markdown546
-rw-r--r--ru-ru/julia-ru.html.markdown750
4 files changed, 1400 insertions, 74 deletions
diff --git a/ru-ru/c-ru.html.markdown b/ru-ru/c-ru.html.markdown
index 874e0821..5988b159 100644
--- a/ru-ru/c-ru.html.markdown
+++ b/ru-ru/c-ru.html.markdown
@@ -1,6 +1,6 @@
---
language: c
-filename: learnc.c
+filename: learnc-ru.c
contributors:
- ["Adam Bard", "http://adambard.com/"]
- ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"]
@@ -480,4 +480,4 @@ void str_reverse_through_pointer(char *str_in) {
Также не забывайте, что [Google](http://google.com) и [Яндекс](http://yandex.ru) – ваши хорошие друзья.
-[1] http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member \ No newline at end of file
+[1] http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member
diff --git a/ru-ru/go-ru.html.markdown b/ru-ru/go-ru.html.markdown
index 27b5d894..ffda01b7 100644
--- a/ru-ru/go-ru.html.markdown
+++ b/ru-ru/go-ru.html.markdown
@@ -3,8 +3,12 @@ language: Go
filename: learngo-ru.go
contributors:
- ["Sonia Keys", "https://github.com/soniakeys"]
+ - ["Christopher Bess", "https://github.com/cbess"]
+ - ["Jesse Johnson", "https://github.com/holocronweaver"]
+ - ["Quint Guvernator", "https://github.com/qguv"]
translators:
- ["Artem Medeusheyev", "https://github.com/armed"]
+ - ["Valery Cherepanov", "https://github.com/qumeric"]
lang: ru-ru
---
@@ -17,7 +21,7 @@ Go - это язык общего назначения, целью которо
для создания масштабируемых и многопоточных программ.
Может похвастаться отличной стандартной библиотекой и большим комьюнити, полным
-энтузиазтов.
+энтузиастов.
```go
// Однострочный комментарий
@@ -31,8 +35,9 @@ package main
// Import предназначен для указания зависимостей этого файла.
import (
"fmt" // Пакет в стандартной библиотеке Go
- "net/http" // Да, это web server!
+ "net/http" // Да, это веб-сервер!
"strconv" // Конвертирование типов в строки и обратно
+ m "math" // Импортировать math под локальным именем m.
)
// Объявление функции. Main это специальная функция, служащая точкой входа для
@@ -40,7 +45,7 @@ import (
// скобки.
func main() {
// Println выводит строку в stdout.
- // В данном случае фигурирует вызов функции из пакета fmt.
+ // Данная функция находится в пакете fmt.
fmt.Println("Hello world!")
// Вызов другой функции из текущего пакета.
@@ -55,57 +60,57 @@ func beyondHello() {
// Краткое определение := позволяет объявить перменную с автоматической
// подстановкой типа из значения.
y := 4
- sum, prod := learnMultiple(x, y) // функция возвращает два значения
- fmt.Println("sum:", sum, "prod:", prod) // простой вывод
+ sum, prod := learnMultiple(x, y) // Функция возвращает два значения.
+ fmt.Println("sum:", sum, "prod:", prod) // Простой вывод.
learnTypes() // < y minutes, learn more!
}
// Функция имеющая входные параметры и возврат нескольких значений.
func learnMultiple(x, y int) (sum, prod int) {
- return x + y, x * y // возврат двух результатов
+ return x + y, x * y // Возврат двух значений.
}
// Некотрые встроенные типы и литералы.
func learnTypes() {
// Краткое определение переменной говорит само за себя.
- s := "Learn Go!" // тип string
+ s := "Learn Go!" // Тип string.
s2 := `"Чистый" строковой литерал
-может содержать переносы строк` // тоже тип данных string
+может содержать переносы строк` // Тоже тип данных string
- // символ не из ASCII. Исходный код Go в кодировке UTF-8.
- g := 'Σ' // тип rune, это алиас для типа uint32, содержит юникод символ
+ // Символ не из ASCII. Исходный код Go в кодировке UTF-8.
+ g := 'Σ' // тип rune, это алиас для типа uint32, содержит символ юникода.
- f := 3.14195 // float64, 64-х битное число с плавающей точкой (IEEE-754)
- c := 3 + 4i // complex128, внутри себя содержит два float64
+ f := 3.14195 // float64, 64-х битное число с плавающей точкой (IEEE-754).
+ c := 3 + 4i // complex128, внутри себя содержит два float64.
- // Синтаксис var с инициализациями
- var u uint = 7 // беззнаковое, но размер зависит от реализации, как и у int
+ // Синтаксис var с инициализациями.
+ var u uint = 7 // Беззнаковое, но размер зависит от реализации, как и у int.
var pi float32 = 22. / 7
// Синтаксис приведения типа с кратким определением
- n := byte('\n') // byte алиас для uint8
+ n := byte('\n') // byte – это алиас для uint8.
- // Массивы (Array) имеют фиксированный размер на момент компиляции.
- var a4 [4]int // массив из 4-х int, проинициализирован нулями
- a3 := [...]int{3, 1, 5} // массив из 3-х int, ручная инициализация
+ // Массивы имеют фиксированный размер на момент компиляции.
+ var a4 [4]int // массив из 4-х int, инициализирован нулями.
+ a3 := [...]int{3, 1, 5} // массив из 3-х int, ручная инициализация.
- // Slice имеют динамическую длину. И массивы и slice-ы имеют каждый свои
- // преимущества, но slice-ы используются гораздо чаще.
- s3 := []int{4, 5, 9} // по сравнению с a3 тут нет троеточия
- s4 := make([]int, 4) // выделение памяти для slice из 4-х int (нули)
- var d2 [][]float64 // только объявление, память не выделяется
- bs := []byte("a slice") // конвертирование строки в slice байтов
+ // Слайсы (slices) имеют динамическую длину. И массивы, и слайсы имеют свои
+ // преимущества, но слайсы используются гораздо чаще.
+ s3 := []int{4, 5, 9} // Сравните с a3. Тут нет троеточия.
+ s4 := make([]int, 4) // Выделение памяти для слайса из 4-х int (нули).
+ var d2 [][]float64 // Только объявление, память не выделяется.
+ bs := []byte("a slice") // Синтаксис приведения типов.
- p, q := learnMemory() // объявление p и q как указателей на int.
+ p, q := learnMemory() // Объявление p и q как указателей на int.
fmt.Println(*p, *q) // * извлекает указатель. Печатает два int-а.
- // Map как словарь или хеш теблица из других языков является ассоциативным
- // массивом с динамически изменяемым размером.
+ // Map, также как и словарь или хеш из некоторых других языков, является
+ // ассоциативным массивом с динамически изменяемым размером.
m := map[string]int{"three": 3, "four": 4}
m["one"] = 1
- delete(m, "three") // встроенная функция, удаляет элемент из map-а.
+ delete(m, "three") // Встроенная функция, удаляет элемент из map-а.
// Неиспользуемые переменные в Go являются ошибкой.
// Нижнее подчеркивание позволяет игнорировать такие переменные.
@@ -113,79 +118,91 @@ func learnTypes() {
// Вывод считается использованием переменной.
fmt.Println(s, c, a4, s3, d2, m)
- learnFlowControl() // идем далее
+ learnFlowControl() // Идем дальше.
}
// У Go есть полноценный сборщик мусора. В нем есть указатели но нет арифметики
-// указатеей. Вы можете допустить ошибку с указателем на nil, но не с его
-// инкрементацией.
+// указателей. Вы можете допустить ошибку с указателем на nil, но не с
+// инкрементацией указателя.
func learnMemory() (p, q *int) {
// Именованные возвращаемые значения p и q являются указателями на int.
- p = new(int) // встроенная функция new выделяет память.
+ p = new(int) // Встроенная функция new выделяет память.
// Выделенный int проинициализирован нулем, p больше не содержит nil.
- s := make([]int, 20) // Выделение единого блока памяти под 20 int-ов,
- s[3] = 7 // назначение одному из них,
- r := -2 // опредление еще одной локальной переменной,
- return &s[3], &r // амперсанд обозначает получение адреса переменной.
+ s := make([]int, 20) // Выделение единого блока памяти под 20 int-ов.
+ s[3] = 7 // Присвоить значение одному из них.
+ r := -2 // Определить еще одну локальную переменную.
+ return &s[3], &r // Амперсанд(&) обозначает получение адреса переменной.
}
-func expensiveComputation() int {
- return 1e6
+func expensiveComputation() float64 {
+ return m.Exp(10)
}
func learnFlowControl() {
- // If-ы всегда требуют наличине фигурных скобок, но круглые скобки
- // необязательны.
+ // If-ы всегда требуют наличине фигурных скобок, но не круглых.
if true {
fmt.Println("told ya")
}
// Форматирование кода стандартизировано утилитой "go fmt".
if false {
- // все тлен
+ // Будущего нет.
} else {
- // жизнь прекрасна
+ // Жизнь прекрасна.
}
- // Использоване switch на замену нескольким if-else
- x := 1
+ // Используйте switch вместо нескольких if-else.
+ x := 42.0
switch x {
case 0:
case 1:
- // case-ы в Go не проваливаются, т.е. break по умолчанию
- case 2:
- // не выполнится
+ case 42:
+ // Case-ы в Go не "проваливаются" (неявный break).
+ case 43:
+ // Не выполнится.
}
// For, как и if не требует круглых скобок
- for x := 0; x < 3; x++ { // ++ это операция
+ // Переменные, объявленные в for и if являются локальными.
+ for x := 0; x < 3; x++ { // ++ – это операция.
fmt.Println("итерация", x)
}
- // тут x == 1.
+ // Здесь x == 42.
- // For это единственный цикл в Go, но у него несколько форм.
- for { // бесконечный цикл
- break // не такой уж и бесконечный
- continue // не выполнится
+ // For – это единственный цикл в Go, но у него есть альтернативные формы.
+ for { // Бесконечный цикл.
+ break // Не такой уж и бесконечный.
+ continue // Не выполнится.
}
// Как и в for, := в if-е означает объявление и присвоение значения y,
- // затем проверка y > x.
+ // проверка y > x происходит после.
if y := expensiveComputation(); y > x {
x = y
}
// Функции являются замыканиями.
xBig := func() bool {
- return x > 100 // ссылается на x, объявленый выше switch.
+ return x > 10000 // Ссылается на x, объявленый выше switch.
}
- fmt.Println("xBig:", xBig()) // true (т.к. мы присвоили x = 1e6)
- x /= 1e5 // тут х == 10
- fmt.Println("xBig:", xBig()) // теперь false
+ fmt.Println("xBig:", xBig()) // true (т.к. мы присвоили x = e^10).
+ x = 1.3e3 // Тут х == 1300
+ fmt.Println("xBig:", xBig()) // Теперь false.
// Метки, куда же без них, их все любят.
goto love
love:
+ learnDefer() // Быстрый обзор важного ключевого слова.
learnInterfaces() // О! Интерфейсы, идем далее.
}
-// Объявление Stringer как интерфейса с одним мметодом, String.
+func learnDefer() (ok bool) {
+ // Отложенные(deferred) выражения выполняются сразу перед тем, как функция
+ // возвратит значение.
+ defer fmt.Println("deferred statements execute in reverse (LIFO) order.")
+ defer fmt.Println("\nThis line is being printed first because")
+ // defer широко используется для закрытия файлов, чтобы закрывающая файл
+ // функция находилась близко к открывающей.
+ return true
+}
+
+// Объявление Stringer как интерфейса с одним методом, String.
type Stringer interface {
String() string
}
@@ -196,35 +213,48 @@ type pair struct {
}
// Объявление метода для типа pair. Теперь pair реализует интерфейс Stringer.
-func (p pair) String() string { // p в данном случае называют receiver-ом
- // Sprintf - еще одна функция из пакета fmt.
+func (p pair) String() string { // p в данном случае называют receiver-ом.
+ // Sprintf – еще одна функция из пакета fmt.
// Обращение к полям p через точку.
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
func learnInterfaces() {
// Синтаксис с фигурными скобками это "литерал структуры". Он возвращает
- // проинициализированную структуру, а оператор := присваивает ее в p.
+ // проинициализированную структуру, а оператор := присваивает её p.
p := pair{3, 4}
- fmt.Println(p.String()) // вызов метода String у p, типа pair.
- var i Stringer // объявление i как типа с интерфейсом Stringer.
- i = p // валидно, т.к. pair реализует Stringer.
- // Вызов метода String у i, типа Stringer. Вывод такой же что и выше.
+ fmt.Println(p.String()) // Вызов метода String у переменной p типа pair.
+ var i Stringer // Объявление i как типа с интерфейсом Stringer.
+ i = p // Валидно, т.к. pair реализует Stringer.
+ // Вызов метода String у i типа Stringer. Вывод такой же, что и выше.
fmt.Println(i.String())
// Функции в пакете fmt сами всегда вызывают метод String у объектов для
// получения строкового представления о них.
- fmt.Println(p) // Вывод такой же что и выше. Println вызывает метод String.
- fmt.Println(i) // тоже самое
+ fmt.Println(p) // Вывод такой же, что и выше. Println вызывает метод String.
+ fmt.Println(i) // Вывод такой же, что и выше.
+
+ learnVariadicParams("Учиться", "учиться", "и еще раз учиться!")
+}
+
+// Функции могут иметь варьируемое количество параметров.
+func learnVariadicParams(myStrings ...interface{}) {
+ // Вывести все параметры с помощью итерации.
+ for _, param := range myStrings {
+ fmt.Println("param:", param)
+ }
+
+ // Передать все варьируемые параметры.
+ fmt.Println("params:", fmt.Sprintln(myStrings...))
learnErrorHandling()
}
func learnErrorHandling() {
- // Идиома ", ok" служит для обозначения сработало что-то или нет.
+ // Идиома ", ok" служит для обозначения корректного срабатывания чего-либо.
m := map[int]string{3: "three", 4: "four"}
if x, ok := m[1]; !ok { // ok будет false, потому что 1 нет в map-е.
- fmt.Println("тут никого")
+ fmt.Println("тут никого нет")
} else {
fmt.Print(x) // x содержал бы значение, если бы 1 был в map-е.
}
@@ -237,7 +267,7 @@ func learnErrorHandling() {
learnConcurrency()
}
-// c это тип данных channel (канал), объект для конкуррентного взаимодействия.
+// c – это тип данных channel (канал), объект для конкуррентного взаимодействия.
func inc(i int, c chan int) {
c <- i + 1 // когда channel слева, <- являтся оператором "отправки".
}
@@ -300,7 +330,7 @@ func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
объемную документацию.
Для живого ознакомления рекомендуется почитать исходные коды [стандартной
-библиотеки Go](http://golang.org/src/pkg/). Отлично задокументированая, она
+библиотеки Go](http://golang.org/src/pkg/). Отлично задокументированная, она
является лучшим источником для чтения и понимания Go, его стиля и идиом. Либо
можно, кликнув на имени функции в [документации](http://golang.org/pkg/),
перейти к ее исходным кодам.
diff --git a/ru-ru/haskell-ru.html.markdown b/ru-ru/haskell-ru.html.markdown
new file mode 100644
index 00000000..03e66d05
--- /dev/null
+++ b/ru-ru/haskell-ru.html.markdown
@@ -0,0 +1,546 @@
+---
+language: haskell
+contributors:
+ - ["Adit Bhargava", "http://adit.io"]
+translators:
+ - ["Aleksey Pirogov", "http://astynax.github.io"]
+lang: ru-ru
+---
+
+Haskell разрабатывался, как чистый функциональный язык программирования, применимый на практике. Язык известен благодаря своей системе типов, и "знаменит" благодаря монадам. [Меня][autor] же Haskell заставляет возвращаться к себе снова и снова именно своей элегантностью и [я][autor] получаю истинное удовольствие, программируя на Haskell.
+
+```haskell
+-- Однострочные комментарии начинаются с двух дефисов
+{- Многострочный комментарий
+заключается в пару фигурных скобок с дефисами с внутренней стороны.
+-}
+
+-------------------------------------------------------
+-- 1. Примитивные типы и простейшие операции над ними
+-------------------------------------------------------
+
+-- Числа объявляются просто
+3 -- 3
+
+-- Арифметика тоже выглядит вполне ожидаемо
+1 + 1 -- 2
+8 - 1 -- 7
+10 * 2 -- 20
+35 / 5 -- 7.0
+
+-- Операция деления всегда возвращает действительное число
+35 / 4 -- 8.75
+
+-- Делим нацело так
+35 `div` 4 -- 8
+
+-- Булевы значения - тоже примитивные значения
+True
+False
+
+-- Булева алгебра
+not True -- False
+not False -- True
+1 == 1 -- True
+1 /= 1 -- False
+1 < 10 -- True
+
+-- В примере выше `not`, это функция, принимающая один аргумент.
+-- При вызове функции в Haskell список аргументов
+-- не нужно заключать в скобки - аргументы просто
+-- перечисляются через пробелы сразу после имени функции.
+-- Т.о. типичный вызов выглядит так:
+-- func arg1 arg2 arg3...
+-- Ниже же будет показано, как определять свои функции.
+
+-- Строки и символы
+"Это строка."
+'ы' -- а это символ
+'Нельзя заключать длинные строки в одинарные кавычки.' -- ошибка!
+
+-- Строки можно конкатенировать
+"Привет" ++ ", Мир!" -- "Привет, Мир!"
+
+-- При этом строки - это просто списки символов!
+"Я - строка!" !! 0 -- 'Я'
+
+
+----------------------------------------------------
+-- Списки и Кортежи
+----------------------------------------------------
+
+-- Все элементы списка в Haskell
+-- должны иметь один и тот же тип.
+
+-- Эти два списка - эквивалентны:
+[1, 2, 3, 4, 5]
+[1..5]
+
+-- Haskell позволяет определять даже бесконечные списки!
+[1..] -- список всех натуральных чисел!
+
+-- Бесконечные списки возможно в Haskell потому, что он "ленив".
+-- В Haskell все вычисления производятся тогда и только тогда,
+-- когда их результат потребуется.
+-- Эта стратегия так и называется - "lazy evaluation".
+-- Скажем, если вам нужен тысячный элемент из
+-- списка натуральных чисел (бесконечного) и вы напишете так:
+
+[1..] !! 999 -- 1000
+
+-- То Haskell вычислит элементы этого списка от 1 до 1000...
+-- ... и остановится, ведь последующие элементы пока не нужны.
+-- Это значит, что остальные элементы нашего
+-- "бесконечного" списка не будут вычисляться! По крайней мере,
+-- пока не понадобятся и они.
+
+-- Списки можно объединять
+[1..5] ++ [6..10]
+
+-- И добавлять значения в начало
+0:[1..5] -- [0, 1, 2, 3, 4, 5]
+
+-- А можно обратиться по индексу
+[0..] !! 5 -- 5
+
+-- Вот ещё несколько функций, часто используемых со списками
+head [1..5] -- 1
+tail [1..5] -- [2, 3, 4, 5]
+init [1..5] -- [1, 2, 3, 4]
+last [1..5] -- 5
+
+-- list comprehensions - "формулы" для описания списков
+[x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10]
+
+-- можно указать условие попадания элементов в список
+[x*2 | x <- [1..5], x*2 > 4] -- [6, 8, 10]
+
+-- Списки могут даже состоять из других списков
+[[1,2,3],[4,5,6]] !! 1 !! 2 -- 6 (вторая строка, третий столбец)
+
+-- Кортежи позволяют своим элементам иметь различные типы,
+-- но при этом кортежи имеют фиксированную длину.
+-- Кортеж:
+("haskell", 1)
+
+-- Часто кортежи из двух элементов называются "парами".
+-- Элементы пары можно получать так:
+fst ("haskell", 1) -- "haskell"
+snd ("haskell", 1) -- 1
+
+----------------------------------------------------
+-- 3. Функции
+----------------------------------------------------
+-- Простая функция, принимающая два аргумента
+add a b = a + b
+
+-- Внимание!
+-- Если вы используете ghci (интерактивный интерпретатор Haskell),
+-- вам нужно использовать ключевое слово `let`, примерно так:
+-- let add a b = a + b
+
+-- Вызовем нашу функцию
+add 1 2 -- 3
+
+-- Функцию можно поместить между первым и вторым аргументами,
+-- если заключить её имя в обратные кавычки
+1 `add` 2 -- 3
+
+{- Вы можете также определять функции, имя которых
+вообще не содержит букв! Таки функции и называются "операторами",
+и, да, вы можете определять свои операторы!
+Скажем, оператор целочисленного деления можно определить так -}
+(//) a b = a `div` b
+35 // 4 -- 8
+{- Здесь оператор заключен в скобки - как говорят,
+поставлен в префиксную позицию.
+В префиксной позиции оператор можно не только определять,
+но и вызывать -}
+(+) 1 2 -- 3
+
+-- Охранные выражения (guards) порой удобны,
+-- если наша функция ветвится
+fib x
+ | x < 2 = x
+ | otherwise = fib (x - 1) + fib (x - 2)
+
+{- Сопоставление с образцом (pattern matching)
+чем-то напоминает охранные выражения.
+Здесь мы видим три определения функции fib.
+При вызове функции по имени Haskell использует
+первое определение, к образцу которого
+"подойдет" набор аргументов -}
+fib 1 = 1
+fib 2 = 2
+fib x = fib (x - 1) + fib (x - 2)
+
+-- Pattern matching для кортежей выглядит так
+foo (x, y) = (x + 1, y + 2)
+
+{- Pattern matching для списков устроен чуть сложнее.
+Пусть `x` - первый элемент списка, а `xs` - остальные элементы.
+Тогда операции `head` и `tail` могут быть определены так -}
+myHead (x:xs) = x
+myTail (x:xs) = xs
+
+-- Функцию отображения мы можем написать так
+myMap func [] = []
+myMap func (x:xs) = func x:(myMap func xs)
+
+-- При сопоставлении происходит привязка
+-- элементов значения с именами в образце
+fstPlusThird (a : _ : b : _) = a + b
+fstPlusThird [1,2,3,4,5] -- 4
+-- Значения, для которых вместо имени указано `_`,
+-- игнорируются. Это удобно, когда важен сам факт
+-- совпадения образца
+oneElem [_] = True
+oneElem _ = False
+
+startsWith x (y:_) = x == y
+startsWith _ _ = False
+
+startsWith 'H' "Hello!" -- True
+startsWith 'H' "hello!" -- False
+
+{- Обратите внимание на тот факт,
+что первый аргумент нашей функции `myMap` - тоже функция!
+Функции, подобно `myMap`, принимающие другие функции
+в качестве параметров, или, скажем, возвращающие функции
+в качестве результата, называются
+Функциями Высших Порядков (ФВП, High Order Functions, HOF)
+-}
+
+-- Вместе с ФВП часто используются анонимные функции
+myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7]
+-- Такие функции описываются в виде
+-- \arg1 arg1 .. -> expression
+
+-- Популярные в других языках ФВП присутствуют и в Haskell
+map (\x -> x * 10) [1..5] -- [10, 20, 30, 40, 50]
+filter (\x -> x > 2) [1..5] -- [3, 4, 5]
+
+{- Функция свертки
+(она же `reduce` или `inject` в других языках)
+в Haskell представлены функциями `foldr` и `foldl`.
+Суть свертки можно представить так:
+
+foldl f x0 [x1,x2,x3] -> (f (f (f x0 x1) x2) x3)
+foldr f x0 [x1,x2,x3] -> (f x1 (f x2 (f x3 x0)))
+
+Здесь x0 - начальное значения так называемого "аккумулятора"
+-}
+-- Эти два вызова дают одинаковый результат
+foldr (\x acc -> acc + x) 0 [1..5] -- 15
+foldl (\acc x -> acc + x) 0 [1..5] -- 15
+-- Тут можно даже заменить анонимную функцию на оператор
+foldr (+) 0 [1..5] -- 15
+foldl (+) 0 [1..5] -- 15
+
+-- Зато здесь разница видна
+foldr (\x acc -> (x + 10) : acc) [] [1..3] -- [11, 12, 13]
+foldl (\acc x -> (x + 10) : acc) [] [1..3] -- [13, 12, 11]
+
+{- Часто в качестве начального значения
+удобно брать крайнее значение списка (крайнее слева или справа).
+Для этого есть пара функций - `foldr1` и `foldl1` -}
+foldr1 (+) [1..5] -- 15
+foldl1 (+) [1..5] -- 15
+
+----------------------------------------------------
+-- 4. Больше о функциях
+----------------------------------------------------
+
+{- Каррирование (currying)
+Если в Haskell при вызове функции передать не все аргументы,
+Функция становится "каррированой" - результатом вызова станет
+новая функция, которая при вызове и примет оставшиеся аргументы -}
+
+add a b = a + b
+foo = add 10 -- теперь foo будет принимать число
+ -- и добавлять к нему 10
+foo 5 -- 15
+
+-- Для операторов можно "опустить" любой из двух аргументов
+-- Используя этот факт можно определить
+-- функцию `foo` из кода выше несколько иначе
+foo = (+10)
+foo 5 -- 15
+
+-- Поупражняемся
+map (10-) [1..3] -- [9, 8, 7]
+filter (<5) [1..10] -- [1, 2, 3, 4]
+
+{- Композиция функций
+Функция (.) соединяет пару функций в цепочку.
+К примеру, можно соединить функцию, добавляющую 10,
+с функцией, умножающей на 5 -}
+foo = (*5) . (+10)
+
+-- (5 + 10) * 5 = 75
+foo 5 -- 75
+
+{- Управление приоритетом вычисления
+В Haskell есть функция `$`, которая применяет
+свой первый аргумент ко второму с наименьшим приоритетом
+(обычное применение функций имеет наивысший приоритет)
+Эта функция часто позволяет избежать использования
+"лишних" скобок -}
+head (tail (tail "abcd")) -- 'c'
+head $ tail $ tail "abcd" -- 'c'
+-- того же эффекта иногда можно достичь использованием композиции
+(head . tail . tail) "abcd" -- 'c'
+head . tail . tail $ "abcd" -- 'c'
+{- Тут стоит сразу запомнить, что композиция функций
+возвращает именно новую функцию, как в последнем примере.
+Т.е. можно делать так -}
+third = head . tail . tail
+-- но не так
+third = head $ tail $ tail -- (head (tail (tail))) - ошибка!
+
+----------------------------------------------------
+-- 5. Сигнатуры типов
+----------------------------------------------------
+
+{- Haskell обладает очень сильной системой типов.
+И типизация в Haskell - строгая. Каждое выражение имеет тип,
+который может быть описан сигнатурой.
+Сигнатура записывается в форме
+expression :: type signature
+-}
+
+-- Типы примитивов
+5 :: Integer
+"hello" :: String
+True :: Bool
+
+{- Функции тоже имеют тип
+`not` принимает булево значение и возвращает булев результат
+not :: Bool -> Bool
+
+Вот функция двух аргументов
+add :: Integer -> Integer -> Integer
+
+Тут то мы и видим предпосылки к каррированию: тип
+на самом деле выглядит так (скобки просто обычно опускаются)
+add :: (Integer -> Integer) -> Integer
+т.е. функция принимает аргумент,
+и возвращает функцию от второго аргумента! -}
+
+-- Считается хорошим тоном указывать сигнатуру определений,
+-- которые доступны другим разработчикам (публичны). Пример:
+double :: Integer -> Integer
+double x = x * 2
+
+----------------------------------------------------
+-- 6. Управление потоком исполнения
+----------------------------------------------------
+
+-- Выражение `if`
+haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome"
+
+-- Выражение `if` можно записать и в несколько строк.
+-- Соблюдайте отступы!
+haskell = if 1 == 1
+ then "awesome"
+ else "awful"
+
+-- Так как `if` - выражение, ветка `else` обязательна!
+-- И более того, результаты выражений в ветках `then` и `else`
+-- должны иметь одинаковый тип!
+
+-- `case`-выражение выглядит так
+case args of -- парсим аргументы командной строки
+ "help" -> printHelp
+ "start" -> startProgram
+ _ -> putStrLn "bad args"
+
+-- При вычислении результата `case`-выражения производится
+-- сопоставление с образцом:
+fib x = case x of
+ 1 -> 1
+ 2 -> 1
+ _ -> fib (x - 1) + fib (x - 2)
+
+-- В Haskell нет циклов - вместо них используются рекурсия,
+-- отображение, фильтрация и свертка (map/filter/fold)
+map (*2) [1..5] -- [2, 4, 6, 8, 10]
+
+for array func = map func array
+for [0..3] $ \i -> show i -- ["0", "1", "2", "3"]
+for [0..3] show -- ["0", "1", "2", "3"]
+
+----------------------------------------------------
+-- 7. Пользовательские типы данных
+----------------------------------------------------
+
+-- Создадим свой Haskell-тип данных
+
+data Color = Red | Blue | Green
+
+-- Попробуем использовать
+
+say :: Color -> String
+say Red = "You are Red!"
+say Blue = "You are Blue!"
+say Green = "You are Green!"
+
+-- Типы могут иметь параметры (параметры типов)
+
+data Maybe a = Nothing | Just a
+
+-- Все эти выражения имеют тип `Maybe`
+Just "hello" -- :: `Maybe String`
+Just 1 -- :: `Maybe Int`
+Nothing -- :: `Maybe a` для любого `a`
+
+-- Типы могут быть достаточно сложными
+data Figure = Rectangle (Int, Int) Int Int
+ | Square (Int, Int) Int
+ | Point (Int, Int)
+
+area :: Figure -> Int
+area (Point _) = 0
+area (Square _ s) = s * s
+area (Rectangle _ w h) = w * h
+
+----------------------------------------------------
+-- 8. Ввод-вывод в Haskell
+----------------------------------------------------
+
+-- Полноценно объяснить тему ввода-вывода невозможно
+-- без объяснения монад, но для использования в простых случаях
+-- вводного описания будет достаточно.
+
+-- Когда программа на Haskell выполняется,
+-- вызывается функция с именем `main`.
+-- Эта функция должна вернуть значение типа `IO ()`
+-- Например
+
+main :: IO ()
+main = putStrLn $ "Hello, sky! " ++ (say Blue)
+-- `putStrLn` имеет тип `String -> IO ()`
+
+-- Проще всего реализовать программу с вводом-выводом (IO),
+-- если вы реализуете функцию с типом `String -> String`.
+-- Далее ФВП
+-- interact :: (String -> String) -> IO ()
+-- сделает всё за нас!
+
+countLines :: String -> String
+countLines = show . length . lines
+-- здесь `lines` разделяет строку на список строк
+-- по символу перевода строки
+
+main' :: IO ()
+main' = interact countLines
+
+{- Вы можете думать о типе `IO ()`,
+как о некотором представлении последовательности
+действий, которые должен совершить компьютер.
+Такое представление напоминает программу
+на императивном языке программирования. Для описания
+такой последовательности используется `do`-нотация -}
+
+sayHello :: IO ()
+sayHello = do
+ putStrLn "What is your name?"
+ name <- getLine -- запрашиваем строку и связываем с "name"
+ putStrLn $ "Hello, " ++ name
+
+-- Упражнение:
+-- напишите свою реализацию функции `interact`,
+-- которая запрашивает и обрабатывает только одну строку
+
+{- Код функции `sayHello` не будет исполняться
+при её определении. Единственное место, где IO-действия
+могут быть произведены - функция `main`!
+Чтобы эта программа выполнила действия в функции `sayHello`,
+закомментируйте предыдущее определение функции `main`
+и добавьте новое определение:
+
+main = sayHello -}
+
+{- Давайте подробнее рассмотрим, как работает функция `getLine`
+Её тип:
+ getLine :: IO String
+Вы можете думать, что значение типа `IO a` представляет
+собой компьютерную программу, в результате выполнения которой
+генерируется значение типа `a`, в дополнение
+к остальным эффектам, производимым при выполнении - таким как
+печать текста на экран. Это значение типа `a` мы можем
+сохранить с помощью оператора `<-`. Мы даже можем реализовать
+свое действие, возвращающее значение: -}
+
+action :: IO String
+action = do
+ putStrLn "This is a line. Duh"
+ input1 <- getLine
+ input2 <- getLine
+ -- Тип блока `do` будет соответствовать типу последнего
+ -- выполненного в блоке выражения.
+ -- Заметим, что `return` - не ключевое слово, а функция
+ -- типа `a -> IO a`
+ return (input1 ++ "\n" ++ input2) -- return :: String -> IO String
+
+-- Теперь это действие можно использовать вместо `getLine`:
+
+main'' = do
+ putStrLn "I will echo two lines!"
+ result <- action
+ putStrLn result
+ putStrLn "This was all, folks!"
+
+{- Тип `IO` - пример "монады". Языку Haskell нужны монады,
+чтобы оставаться преимущественно чистым функциональным языком.
+Любые функции, взаимодействующие с внешним миром
+(производящие ввод-вывод) имеют `IO` в своих сигнатурах.
+Это позволяет судить о функции как о "чистой" - такая не будет
+производить ввод-вывод. В ином случая функция - не "чистая".
+
+Такой подход позволяет очень просто разрабатывать многопоточные
+программы - чистые функции, запущенные параллельно
+не будут конфликтовать между собой в борьбе за ресурсы. -}
+
+----------------------------------------------------
+-- 9. Haskell REPL
+----------------------------------------------------
+
+{- Интерактивная консоль Haskell запускается командой `ghci`.
+Теперь можно вводить строки кода на Haskell.
+Связывание значений с именами производится
+с помощью выражения `let`: -}
+
+let foo = 5
+
+-- Тип значения или выражения можно узнать
+-- с помощью команды `:t`:
+
+>:t foo
+foo :: Integer
+
+-- Также можно выполнять действия с типом `IO ()`
+
+> sayHello
+What is your name?
+Friend!
+Hello, Friend!
+
+```
+
+Многое о Haskell, например классы типов и монады невозможно уместить в столь короткую статью. Огромное количество очень интересных идей лежит в основе языка, и именно благодаря этому фундаменту на языке так приятно писать код. Позволю себе привести ещё один маленький пример кода на Haskell - реализацию быстрой сортировки:
+
+```haskell
+qsort [] = []
+qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
+ where lesser = filter (< p) xs
+ greater = filter (>= p) xs
+```
+
+Haskell прост в установке, забирайте [здесь](http://www.haskell.org/platform/) и пробуйте! Это же так интересно!.
+
+Более глубокое погрузиться в язык позволят прекрасные книги
+[Learn you a Haskell](http://learnyouahaskell.com/) и
+[Real World Haskell](http://book.realworldhaskell.org/).
+
+[autor]: http://adit.io имеется в виду автор оригинального текста Adit Bhargava *(примечание переводчика)*
diff --git a/ru-ru/julia-ru.html.markdown b/ru-ru/julia-ru.html.markdown
new file mode 100644
index 00000000..cd55e116
--- /dev/null
+++ b/ru-ru/julia-ru.html.markdown
@@ -0,0 +1,750 @@
+---
+language: julia
+contributors:
+ - ["Leah Hanson", "http://leahhanson.us"]
+translators:
+ - ["Sergey Skovorodkin", "https://github.com/skovorodkin"]
+filename: learnjulia-ru.jl
+lang: ru-ru
+---
+
+Julia — гомоиконный функциональный язык программирования для технических расчётов.
+Несмотря на полную поддержку гомоиконных макросов, функций первого класса и конструкций управления низкого уровня, этот язык так же прост в изучении и применении, как и Python.
+
+Документ описывает текущую dev-версию Julia от 18-о октября 2013 года.
+
+```ruby
+
+# Однострочные комментарии начинаются со знака решётки.
+
+####################################################
+## 1. Примитивные типы данных и операторы
+####################################################
+
+# Всё в Julia — выражение.
+
+# Простые численные типы
+3 # => 3 (Int64)
+3.2 # => 3.2 (Float64)
+2 + 1im # => 2 + 1im (Complex{Int64})
+2//3 # => 2//3 (Rational{Int64})
+
+# Доступны все привычные инфиксные операторы
+1 + 1 # => 2
+8 - 1 # => 7
+10 * 2 # => 20
+35 / 5 # => 7.0
+5 / 2 # => 2.5 # деление Int на Int всегда возвращает Float
+div(5, 2) # => 2 # для округления к нулю используется div
+5 \ 35 # => 7.0
+2 ^ 2 # => 4 # возведение в степень
+12 % 10 # => 2
+
+# С помощью скобок можно изменить приоритет операций
+(1 + 3) * 2 # => 8
+
+# Побитовые операторы
+~2 # => -3 # НЕ (NOT)
+3 & 5 # => 1 # И (AND)
+2 | 4 # => 6 # ИЛИ (OR)
+2 $ 4 # => 6 # сложение по модулю 2 (XOR)
+2 >>> 1 # => 1 # логический сдвиг вправо
+2 >> 1 # => 1 # арифметический сдвиг вправо
+2 << 1 # => 4 # логический/арифметический сдвиг влево
+
+# Функция bits возвращает бинарное представление числа
+bits(12345)
+# => "0000000000000000000000000000000000000000000000000011000000111001"
+bits(12345.0)
+# => "0100000011001000000111001000000000000000000000000000000000000000"
+
+# Логические значения являются примитивами
+true
+false
+
+# Булевы операторы
+!true # => false
+!false # => true
+1 == 1 # => true
+2 == 1 # => false
+1 != 1 # => false
+2 != 1 # => true
+1 < 10 # => true
+1 > 10 # => false
+2 <= 2 # => true
+2 >= 2 # => true
+# Сравнения можно объединять цепочкой
+1 < 2 < 3 # => true
+2 < 3 < 2 # => false
+
+# Строки объявляются с помощью двойных кавычек — "
+"This is a string."
+
+# Символьные литералы создаются с помощью одинарных кавычек — '
+'a'
+
+# Строки индексируются как массивы символов
+"This is a string"[1] # => 'T' # Индексы начинаются с единицы
+# Индексирование не всегда правильно работает для UTF8-строк,
+# поэтому рекомендуется использовать итерирование (map, for-циклы и т.п.).
+
+# Для строковой интерполяции используется знак доллара ($):
+"2 + 2 = $(2 + 2)" # => "2 + 2 = 4"
+# В скобках можно использовать любое выражение языка.
+
+# Другой способ форматирования строк — макрос printf
+@printf "%d is less than %f" 4.5 5.3 # 5 is less than 5.300000
+
+####################################################
+## 2. Переменные и коллекции
+####################################################
+
+# Вывод
+println("I'm Julia. Nice to meet you!")
+
+# Переменные инициализируются без предварительного объявления
+some_var = 5 # => 5
+some_var # => 5
+
+# Попытка доступа к переменной до инициализации вызывает ошибку
+try
+ some_other_var # => ERROR: some_other_var not defined
+catch e
+ println(e)
+end
+
+# Имена переменных начинаются с букв.
+# После первого символа можно использовать буквы, цифры,
+# символы подчёркивания и восклицательные знаки.
+SomeOtherVar123! = 6 # => 6
+
+# Допустимо использование unicode-символов
+☃ = 8 # => 8
+# Это особенно удобно для математических обозначений
+2 * π # => 6.283185307179586
+
+# Рекомендации по именованию:
+# * имена переменных в нижнем регистре, слова разделяются символом
+# подчёркивания ('\_');
+#
+# * для имён типов используется CamelCase;
+#
+# * имена функций и макросов в нижнем регистре
+# без разделения слов символом подчёркивания;
+#
+# * имя функции, изменяющей переданные ей аргументы (in-place function),
+# оканчивается восклицательным знаком.
+
+# Массив хранит последовательность значений, индексируемых с единицы до n:
+a = Int64[] # => пустой массив Int64-элементов
+
+# Одномерный массив объявляется разделёнными запятой значениями.
+b = [4, 5, 6] # => массив из трёх Int64-элементов: [4, 5, 6]
+b[1] # => 4
+b[end] # => 6
+
+# Строки двумерного массива разделяются точкой с запятой.
+# Элементы строк разделяются пробелами.
+matrix = [1 2; 3 4] # => 2x2 Int64 Array: [1 2; 3 4]
+
+# push! и append! добавляют в список новые элементы
+push!(a,1) # => [1]
+push!(a,2) # => [1,2]
+push!(a,4) # => [1,2,4]
+push!(a,3) # => [1,2,4,3]
+append!(a,b) # => [1,2,4,3,4,5,6]
+
+# pop! удаляет из списка последний элемент
+pop!(b) # => возвращает 6; массив b снова равен [4,5]
+
+# Вернём 6 обратно
+push!(b,6) # b снова [4,5,6].
+
+a[1] # => 1 # индексы начинаются с единицы!
+
+# Последний элемент можно получить с помощью end
+a[end] # => 6
+
+# Операции сдвига
+shift!(a) # => 1 and a is now [2,4,3,4,5,6]
+unshift!(a,7) # => [7,2,4,3,4,5,6]
+
+# Восклицательный знак на конце названия функции означает,
+# что функция изменяет переданные ей аргументы.
+arr = [5,4,6] # => массив из 3 Int64-элементов: [5,4,6]
+sort(arr) # => [4,5,6]; но arr равен [5,4,6]
+sort!(arr) # => [4,5,6]; а теперь arr — [4,5,6]
+
+# Попытка доступа за пределами массива выбрасывает BoundsError
+try
+ a[0] # => ERROR: BoundsError() in getindex at array.jl:270
+ a[end+1] # => ERROR: BoundsError() in getindex at array.jl:270
+catch e
+ println(e)
+end
+
+# Вывод ошибок содержит строку и файл, где произошла ошибка,
+# даже если это случилось в стандартной библиотеке.
+# Если вы собрали Julia из исходных кодов,
+# то найти эти файлы можно в директории base.
+
+# Создавать массивы можно из последовательности
+a = [1:5] # => массив из 5 Int64-элементов: [1,2,3,4,5]
+
+# Срезы
+a[1:3] # => [1, 2, 3]
+a[2:] # => [2, 3, 4, 5]
+a[2:end] # => [2, 3, 4, 5]
+
+# splice! удаляет элемент из массива
+# Remove elements from an array by index with splice!
+arr = [3,4,5]
+splice!(arr,2) # => 4 ; arr теперь равен [3,5]
+
+# append! объединяет списки
+b = [1,2,3]
+append!(a,b) # теперь a равен [1, 2, 3, 4, 5, 1, 2, 3]
+
+# Проверка на вхождение
+in(1, a) # => true
+
+# Длина списка
+length(a) # => 8
+
+# Кортеж — неизменяемая структура.
+tup = (1, 2, 3) # => (1,2,3) # кортеж (Int64,Int64,Int64).
+tup[1] # => 1
+try:
+ tup[1] = 3 # => ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64)
+catch e
+ println(e)
+end
+
+# Многие функции над списками работают и для кортежей
+length(tup) # => 3
+tup[1:2] # => (1,2)
+in(2, tup) # => true
+
+# Кортежи можно распаковывать в переменные
+a, b, c = (1, 2, 3) # => (1,2,3) # a = 1, b = 2 и c = 3
+
+# Скобки из предыдущего примера можно опустить
+d, e, f = 4, 5, 6 # => (4,5,6)
+
+# Кортеж из одного элемента не равен значению этого элемента
+(1,) == 1 # => false
+(1) == 1 # => true
+
+# Обмен значений
+e, d = d, e # => (5,4) # d = 5, e = 4
+
+
+# Словари содержат ассоциативные массивы
+empty_dict = Dict() # => Dict{Any,Any}()
+
+# Для создания словаря можно использовать литерал
+filled_dict = ["one"=> 1, "two"=> 2, "three"=> 3]
+# => Dict{ASCIIString,Int64}
+
+# Значения ищутся по ключу с помощью оператора []
+filled_dict["one"] # => 1
+
+# Получить все ключи
+keys(filled_dict)
+# => KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2])
+# Заметьте, словарь не запоминает порядок, в котором добавляются ключи.
+
+# Получить все значения.
+values(filled_dict)
+# => ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2])
+# То же касается и порядка значений.
+
+# Проверка вхождения ключа в словарь
+in(("one", 1), filled_dict) # => true
+in(("two", 3), filled_dict) # => false
+haskey(filled_dict, "one") # => true
+haskey(filled_dict, 1) # => false
+
+# Попытка обратиться к несуществующему ключу выбросит ошибку
+try
+ filled_dict["four"] # => ERROR: key not found: four in getindex at dict.jl:489
+catch e
+ println(e)
+end
+
+# Используйте метод get со значением по умолчанию, чтобы избежать этой ошибки
+# get(dictionary,key,default_value)
+get(filled_dict,"one",4) # => 1
+get(filled_dict,"four",4) # => 4
+
+# Для коллекций неотсортированных уникальных элементов используйте Set
+empty_set = Set() # => Set{Any}()
+# Инициализация множества
+filled_set = Set(1,2,2,3,4) # => Set{Int64}(1,2,3,4)
+
+# Добавление элементов
+push!(filled_set,5) # => Set{Int64}(5,4,2,3,1)
+
+# Проверка вхождения элементов во множество
+in(2, filled_set) # => true
+in(10, filled_set) # => false
+
+# Функции для получения пересечения, объединения и разницы.
+other_set = Set(3, 4, 5, 6) # => Set{Int64}(6,4,5,3)
+intersect(filled_set, other_set) # => Set{Int64}(3,4,5)
+union(filled_set, other_set) # => Set{Int64}(1,2,3,4,5,6)
+setdiff(Set(1,2,3,4),Set(2,3,5)) # => Set{Int64}(1,4)
+
+
+####################################################
+## 3. Поток управления
+####################################################
+
+# Создадим переменную
+some_var = 5
+
+# Выражение if. Отступы не имеют значения.
+if some_var > 10
+ println("some_var is totally bigger than 10.")
+elseif some_var < 10 # Необязательная ветка elseif.
+ println("some_var is smaller than 10.")
+else # else-ветка также опциональна.
+ println("some_var is indeed 10.")
+end
+# => prints "some var is smaller than 10"
+
+
+# Цикл for проходит по итерируемым объектам
+# Примеры итерируемых типов: Range, Array, Set, Dict и String.
+for animal=["dog", "cat", "mouse"]
+ println("$animal is a mammal")
+ # Для вставки значения переменной или выражения в строку используется $
+end
+# Выведет:
+# dog is a mammal
+# cat is a mammal
+# mouse is a mammal
+
+# Другой вариант записи.
+for animal in ["dog", "cat", "mouse"]
+ println("$animal is a mammal")
+end
+# Выведет:
+# dog is a mammal
+# cat is a mammal
+# mouse is a mammal
+
+for a in ["dog"=>"mammal","cat"=>"mammal","mouse"=>"mammal"]
+ println("$(a[1]) is a $(a[2])")
+end
+# Выведет:
+# dog is a mammal
+# cat is a mammal
+# mouse is a mammal
+
+for (k,v) in ["dog"=>"mammal","cat"=>"mammal","mouse"=>"mammal"]
+ println("$k is a $v")
+end
+# Выведет:
+# dog is a mammal
+# cat is a mammal
+# mouse is a mammal
+
+# Цикл while выполняется до тех пор, пока верно условие
+x = 0
+while x < 4
+ println(x)
+ x += 1 # Короткая запись x = x + 1
+end
+# Выведет:
+# 0
+# 1
+# 2
+# 3
+
+# Обработка исключений
+try
+ error("help")
+catch e
+ println("caught it $e")
+end
+# => caught it ErrorException("help")
+
+
+####################################################
+## 4. Функции
+####################################################
+
+# Для определения новой функции используется ключевое слово 'function'
+#function имя(аргументы)
+# тело...
+#end
+function add(x, y)
+ println("x is $x and y is $y")
+
+ # Функция возвращает значение последнего выражения
+ x + y
+end
+
+add(5, 6) # => Вернёт 11, напечатав "x is 5 and y is 6"
+
+# Функция может принимать переменное количество позиционных аргументов.
+function varargs(args...)
+ return args
+ # для возвращения из функции в любом месте используется 'return'
+end
+# => varargs (generic function with 1 method)
+
+varargs(1,2,3) # => (1,2,3)
+
+# Многоточие (...) — это splat.
+# Мы только что воспользовались им в определении функции.
+# Также его можно использовать при вызове функции,
+# где он преобразует содержимое массива или кортежа в список аргументов.
+Set([1,2,3]) # => Set{Array{Int64,1}}([1,2,3]) # формирует множество массивов
+Set([1,2,3]...) # => Set{Int64}(1,2,3) # эквивалентно Set(1,2,3)
+
+x = (1,2,3) # => (1,2,3)
+Set(x) # => Set{(Int64,Int64,Int64)}((1,2,3)) # множество кортежей
+Set(x...) # => Set{Int64}(2,3,1)
+
+
+# Опциональные позиционные аргументы
+function defaults(a,b,x=5,y=6)
+ return "$a $b and $x $y"
+end
+
+defaults('h','g') # => "h g and 5 6"
+defaults('h','g','j') # => "h g and j 6"
+defaults('h','g','j','k') # => "h g and j k"
+try
+ defaults('h') # => ERROR: no method defaults(Char,)
+ defaults() # => ERROR: no methods defaults()
+catch e
+ println(e)
+end
+
+# Именованные аргументы
+function keyword_args(;k1=4,name2="hello") # обратите внимание на ;
+ return ["k1"=>k1,"name2"=>name2]
+end
+
+keyword_args(name2="ness") # => ["name2"=>"ness","k1"=>4]
+keyword_args(k1="mine") # => ["k1"=>"mine","name2"=>"hello"]
+keyword_args() # => ["name2"=>"hello","k2"=>4]
+
+# В одной функции можно совмещать все виды аргументов
+function all_the_args(normal_arg, optional_positional_arg=2; keyword_arg="foo")
+ println("normal arg: $normal_arg")
+ println("optional arg: $optional_positional_arg")
+ println("keyword arg: $keyword_arg")
+end
+
+all_the_args(1, 3, keyword_arg=4)
+# Выведет:
+# normal arg: 1
+# optional arg: 3
+# keyword arg: 4
+
+# Функции в Julia первого класса
+function create_adder(x)
+ adder = function (y)
+ return x + y
+ end
+ return adder
+end
+
+# Анонимная функция
+(x -> x > 2)(3) # => true
+
+# Эта функция идентичная предыдущей версии create_adder
+function create_adder(x)
+ y -> x + y
+end
+
+# Если есть желание, можно воспользоваться полным вариантом
+function create_adder(x)
+ function adder(y)
+ x + y
+ end
+ adder
+end
+
+add_10 = create_adder(10)
+add_10(3) # => 13
+
+
+# Встроенные функции высшего порядка
+map(add_10, [1,2,3]) # => [11, 12, 13]
+filter(x -> x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
+
+# Списковые сборки
+[add_10(i) for i=[1, 2, 3]] # => [11, 12, 13]
+[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13]
+
+####################################################
+## 5. Типы
+####################################################
+
+# Julia has a type system.
+# Каждое значение имеет тип, но переменные не определяют тип значения.
+# Функция `typeof` возвращает тип значения.
+typeof(5) # => Int64
+
+# Types are first-class values
+# Типы являются значениями первого класса
+typeof(Int64) # => DataType
+typeof(DataType) # => DataType
+# Тип DataType представляет типы, включая себя самого.
+
+# Типы используются в качестве документации, для оптимизации и организации.
+# Статически типы не проверяются.
+
+# Пользователь может определять свои типы
+# Типы похожи на структуры в других языках
+# Новые типы определяются с помощью ключевого слова `type`
+
+# type Name
+# field::OptionalType
+# ...
+# end
+type Tiger
+ taillength::Float64
+ coatcolor # отсутствие типа равносильно `::Any`
+end
+
+# Аргументы конструктора по умолчанию — свойства типа
+# в порядке их определения.
+tigger = Tiger(3.5,"orange") # => Tiger(3.5,"orange")
+
+# Тип объекта по сути является конструктором значений такого типа
+sherekhan = typeof(tigger)(5.6,"fire") # => Tiger(5.6,"fire")
+
+# Эти типы, похожие на структуры, называются конкретными.
+# Можно создавать объекты таких типов, но не их подтипы.
+# Другой вид типов — абстрактные типы.
+
+# abstract Name
+abstract Cat # просто имя и точка в иерархии типов
+
+# Объекты абстрактных типов создавать нельзя,
+# но зато от них можно наследовать подтипы.
+# Например, Number — это абстрактный тип.
+subtypes(Number) # => 6 элементов в массиве Array{Any,1}:
+ # Complex{Float16}
+ # Complex{Float32}
+ # Complex{Float64}
+ # Complex{T<:Real}
+ # ImaginaryUnit
+ # Real
+subtypes(Cat) # => пустой массив Array{Any,1}
+
+# У всех типов есть супертип. Для его определения есть функция `super`.
+typeof(5) # => Int64
+super(Int64) # => Signed
+super(Signed) # => Real
+super(Real) # => Number
+super(Number) # => Any
+super(super(Signed)) # => Number
+super(Any) # => Any
+# Все эти типы, за исключением Int64, абстрактные.
+
+# Для создания подтипа используется оператор <:
+type Lion <: Cat # Lion — это подтип Cat
+ mane_color
+ roar::String
+end
+
+# У типа может быть несколько конструкторов.
+# Для создания нового определите функцию с именем, как у типа,
+# и вызовите имеющийся конструктор.
+Lion(roar::String) = Lion("green",roar)
+# Мы создали внешний (т.к. он находится вне определения типа) конструктор.
+
+type Panther <: Cat # Panther — это тоже подтип Cat
+ eye_color
+
+ # Определим свой конструктор вместо конструктора по умолчанию
+ Panther() = new("green")
+end
+# Использование внутренних конструкторов позволяет
+# определять, как будут создаваться объекты типов.
+# Но по возможности стоит пользоваться внешними конструкторами.
+
+####################################################
+## 6. Мультиметоды
+####################################################
+
+# Все именованные функции являются generic-функциями,
+# т.е. все они состоят из разных методов.
+# Каждый конструктор типа Lion — это метод generic-функции Lion.
+
+# Приведём пример без использования конструкторов, создадим функцию meow
+
+# Определения Lion, Panther и Tiger
+function meow(animal::Lion)
+ animal.roar # доступ к свойству типа через точку
+end
+
+function meow(animal::Panther)
+ "grrr"
+end
+
+function meow(animal::Tiger)
+ "rawwwr"
+end
+
+# Проверка
+meow(tigger) # => "rawwr"
+meow(Lion("brown","ROAAR")) # => "ROAAR"
+meow(Panther()) # => "grrr"
+
+# Вспомним иерархию типов
+issubtype(Tiger,Cat) # => false
+issubtype(Lion,Cat) # => true
+issubtype(Panther,Cat) # => true
+
+# Определим функцию, принимающую на вход объекты типа Cat
+function pet_cat(cat::Cat)
+ println("The cat says $(meow(cat))")
+end
+
+pet_cat(Lion("42")) # => выведет "The cat says 42"
+try
+ pet_cat(tigger) # => ERROR: no method pet_cat(Tiger,)
+catch e
+ println(e)
+end
+
+# В объектно-ориентированных языках распространена одиночная диспетчеризация —
+# подходящий метод выбирается на основе типа первого аргумента.
+# В Julia все аргументы участвуют в выборе нужного метода.
+
+# Чтобы понять разницу, определим функцию с несколькими аргументами.
+function fight(t::Tiger,c::Cat)
+ println("The $(t.coatcolor) tiger wins!")
+end
+# => fight (generic function with 1 method)
+
+fight(tigger,Panther()) # => выведет The orange tiger wins!
+fight(tigger,Lion("ROAR")) # => выведет The orange tiger wins!
+
+# Переопределим поведение функции, если Cat-объект является Lion-объектом
+fight(t::Tiger,l::Lion) = println("The $(l.mane_color)-maned lion wins!")
+# => fight (generic function with 2 methods)
+
+fight(tigger,Panther()) # => выведет The orange tiger wins!
+fight(tigger,Lion("ROAR")) # => выведет The green-maned lion wins!
+
+# Драться можно не только с тиграми!
+fight(l::Lion,c::Cat) = println("The victorious cat says $(meow(c))")
+# => fight (generic function with 3 methods)
+
+fight(Lion("balooga!"),Panther()) # => выведет The victorious cat says grrr
+try
+ fight(Panther(),Lion("RAWR")) # => ERROR: no method fight(Panther,Lion)
+catch
+end
+
+# Вообще, пускай кошачьи могут первыми проявлять агрессию
+fight(c::Cat,l::Lion) = println("The cat beats the Lion")
+# => Warning: New definition
+# fight(Cat,Lion) at none:1
+# is ambiguous with
+# fight(Lion,Cat) at none:2.
+# Make sure
+# fight(Lion,Lion)
+# is defined first.
+#fight (generic function with 4 methods)
+
+# Предупреждение говорит, что неясно, какой из методов вызывать:
+fight(Lion("RAR"),Lion("brown","rarrr")) # => выведет The victorious cat says rarrr
+# Результат может оказаться разным в разных версиях Julia
+
+fight(l::Lion,l2::Lion) = println("The lions come to a tie")
+fight(Lion("RAR"),Lion("brown","rarrr")) # => выведет The lions come to a tie
+
+
+# Под капотом
+# Язык позволяет посмотреть на сгенерированные ассемблерный и LLVM-код.
+
+square_area(l) = l * l # square_area (generic function with 1 method)
+
+square_area(5) #25
+
+# Что происходит, когда мы передаём функции square_area целое число?
+code_native(square_area, (Int32,))
+ # .section __TEXT,__text,regular,pure_instructions
+ # Filename: none
+ # Source line: 1 # Вводная часть
+ # push RBP
+ # mov RBP, RSP
+ # Source line: 1
+ # movsxd RAX, EDI #
+ # imul RAX, RAX #
+ # pop RBP #
+ # ret #
+
+code_native(square_area, (Float32,))
+ # .section __TEXT,__text,regular,pure_instructions
+ # Filename: none
+ # Source line: 1
+ # push RBP
+ # mov RBP, RSP
+ # Source line: 1
+ # vmulss XMM0, XMM0, XMM0 # Произведение чисел одинарной точности (AVX)
+ # pop RBP
+ # ret
+
+code_native(square_area, (Float64,))
+ # .section __TEXT,__text,regular,pure_instructions
+ # Filename: none
+ # Source line: 1
+ # push RBP
+ # mov RBP, RSP
+ # Source line: 1
+ # vmulsd XMM0, XMM0, XMM0 # Произведение чисел двойной точности (AVX)
+ # pop RBP
+ # ret
+ #
+# Если хотя бы один из аргументов является числом с плавающей запятой,
+# то Julia будет использовать соответствующие инструкции.
+# Вычислим площать круга
+circle_area(r) = pi * r * r # circle_area (generic function with 1 method)
+circle_area(5) # 78.53981633974483
+
+code_native(circle_area, (Int32,))
+ # .section __TEXT,__text,regular,pure_instructions
+ # Filename: none
+ # Source line: 1
+ # push RBP
+ # mov RBP, RSP
+ # Source line: 1
+ # vcvtsi2sd XMM0, XMM0, EDI # Загрузить целое число (r)
+ # movabs RAX, 4593140240 # Загрузить pi
+ # vmulsd XMM1, XMM0, QWORD PTR [RAX] # pi * r
+ # vmulsd XMM0, XMM0, XMM1 # (pi * r) * r
+ # pop RBP
+ # ret
+ #
+
+code_native(circle_area, (Float64,))
+ # .section __TEXT,__text,regular,pure_instructions
+ # Filename: none
+ # Source line: 1
+ # push RBP
+ # mov RBP, RSP
+ # movabs RAX, 4593140496
+ # Source line: 1
+ # vmulsd XMM1, XMM0, QWORD PTR [RAX]
+ # vmulsd XMM0, XMM1, XMM0
+ # pop RBP
+ # ret
+ #
+```
+
+## Что дальше?
+
+Для более подробной информации читайте [документацию по языку](http://docs.julialang.org/en/latest/manual/)
+
+Если вам нужна помощь, задавайте вопросы в [списке рассылки](https://groups.google.com/forum/#!forum/julia-users).