summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ru-ru/crystal-ru.html.markdown584
1 files changed, 584 insertions, 0 deletions
diff --git a/ru-ru/crystal-ru.html.markdown b/ru-ru/crystal-ru.html.markdown
new file mode 100644
index 00000000..87d12f23
--- /dev/null
+++ b/ru-ru/crystal-ru.html.markdown
@@ -0,0 +1,584 @@
+---
+language: crystal
+filename: learncrystal-ru.cr
+contributors:
+ - ["Vitalii Elenhaupt", "http://veelenga.com"]
+ - ["Arnaud Fernandés", "https://github.com/TechMagister/"]
+translators:
+ - ["Den Patin", "https://github.com/denpatin"]
+lang: ru-ru
+---
+
+```crystal
+# — так начинается комментарий
+
+
+# Всё является объектом
+nil.class #=> Nil
+100.class #=> Int32
+true.class #=> Bool
+
+# Возвращают false только nil, false и пустые указатели
+!nil #=> true : Bool
+!false #=> true : Bool
+!0 #=> false : Bool
+
+
+# Целые числа
+
+1.class #=> Int32
+
+# Четыре типа целых чисел со знаком
+1_i8.class #=> Int8
+1_i16.class #=> Int16
+1_i32.class #=> Int32
+1_i64.class #=> Int64
+
+# Четыре типа целых чисел без знака
+1_u8.class #=> UInt8
+1_u16.class #=> UInt16
+1_u32.class #=> UInt32
+1_u64.class #=> UInt64
+
+2147483648.class #=> Int64
+9223372036854775808.class #=> UInt64
+
+# Двоичные числа
+0b1101 #=> 13 : Int32
+
+# Восьмеричные числа
+0o123 #=> 83 : Int32
+
+# Шестнадцатеричные числа
+0xFE012D #=> 16646445 : Int32
+0xfe012d #=> 16646445 : Int32
+
+# Числа с плавающей точкой
+
+1.0.class #=> Float64
+
+# Два типа чисел с плавающей запятой
+1.0_f32.class #=> Float32
+1_f32.class #=> Float32
+
+1e10.class #=> Float64
+1.5e10.class #=> Float64
+1.5e-7.class #=> Float64
+
+
+# Символьные литералы
+
+'a'.class #=> Char
+
+# Восьмеричный код символа
+'\101' #=> 'A' : Char
+
+# Код символа Unicode
+'\u0041' #=> 'A' : Char
+
+
+# Строки
+
+"s".class #=> String
+
+# Строки неизменяемы
+s = "hello, " #=> "hello, " : String
+s.object_id #=> 134667712 : UInt64
+s += "Crystal" #=> "hello, Crystal" : String
+s.object_id #=> 142528472 : UInt64
+
+# Поддерживается интерполяция строк
+"sum = #{1 + 2}" #=> "sum = 3" : String
+
+# Поддерживается многострочность
+"This is
+ multiline string"
+
+# Строка с двойными кавычками
+%(hello "world") #=> "hello \"world\""
+
+
+# Символы — константы без значения, определяемые только именем. Часто
+# используются вместо часто используемых строк для лучшей производительности.
+# На внутреннем уровне они представлены как Int32.
+
+:symbol.class #=> Symbol
+
+sentence = :question? # :"question?" : Symbol
+
+sentence == :question? #=> true : Bool
+sentence == :exclamation! #=> false : Bool
+sentence == "question?" #=> false : Bool
+
+
+# Массивы
+
+[1, 2, 3].class #=> Array(Int32)
+[1, "hello", 'x'].class #=> Array(Int32 | String | Char)
+
+# При объявлении пустого массива необходимо указать тип его элементов
+[] # Syntax error: for empty arrays use '[] of ElementType'
+[] of Int32 #=> [] : Array(Int32)
+Array(Int32).new #=> [] : Array(Int32)
+
+# Элементы внутри массива имеют свои индексы
+array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] : Array(Int32)
+array[0] #=> 1 : Int32
+array[10] # raises IndexError
+array[-6] # raises IndexError
+array[10]? #=> nil : (Int32 | Nil)
+array[-6]? #=> nil : (Int32 | Nil)
+
+# Можно получать элементы по индексу с конца
+array[-1] #=> 5
+
+# С начала и с указанием размера итогового массива
+array[2, 3] #=> [3, 4, 5]
+
+# Или посредством указания диапазона
+array[1..3] #=> [2, 3, 4]
+
+# Добавление в массив
+array << 6 #=> [1, 2, 3, 4, 5, 6]
+
+# Удаление элемента из конца массива
+array.pop #=> 6
+array #=> [1, 2, 3, 4, 5]
+
+# Удаление элемента из начала массива
+array.shift #=> 1
+array #=> [2, 3, 4, 5]
+
+# Проверка на наличие элемента в массиве
+array.includes? 3 #=> true
+
+# Синтаксический сахар для массива строк и символов
+%w(one two three) #=> ["one", "two", "three"] : Array(String)
+%i(one two three) #=> [:one, :two, :three] : Array(Symbol)
+
+# Массивоподобный синтаксис используется и для других типов, только если для
+# них определены методы .new и #<<
+set = Set{1, 2, 3} #=> [1, 2, 3]
+set.class #=> Set(Int32)
+
+# Вышеприведенное эквивалентно следующему
+set = Set(typeof(1, 2, 3)).new
+set << 1
+set << 2
+set << 3
+
+
+# Хэши
+
+{1 => 2, 3 => 4}.class #=> Hash(Int32, Int32)
+{1 => 2, 'a' => 3}.class #=> Hash(Int32 | Char, Int32)
+
+# При объявлении пустого хэша необходимо указать типы ключа и значения
+{} # Syntax error
+{} of Int32 => Int32 # {}
+Hash(Int32, Int32).new # {}
+
+# Значения в хэше легко найти по ключу
+hash = {"color" => "green", "number" => 5}
+hash["color"] #=> "green"
+hash["no_such_key"] #=> Missing hash key: "no_such_key" (KeyError)
+hash["no_such_key"]? #=> nil
+
+# Проверка наличия ключа в хэше
+hash.has_key? "color" #=> true
+
+# Синтаксический сахар для символьных и строковых ключей
+{key1: 'a', key2: 'b'} # {:key1 => 'a', :key2 => 'b'}
+{"key1": 'a', "key2": 'b'} # {"key1" => 'a', "key2" => 'b'}
+
+# Хэшеподобный синтаксис используется и для других типов, только если для них
+# определены методы .new и #[]=
+class MyType
+ def []=(key, value)
+ puts "do stuff"
+ end
+end
+
+MyType{"foo" => "bar"}
+
+# Вышеприведенное эквивалентно следующему
+tmp = MyType.new
+tmp["foo"] = "bar"
+tmp
+
+
+# Диапазоны
+
+1..10 #=> Range(Int32, Int32)
+Range.new(1, 10).class #=> Range(Int32, Int32)
+
+# Включающий и исключающий диапазоны
+(3..5).to_a #=> [3, 4, 5]
+(3...5).to_a #=> [3, 4]
+
+# Проверка на вхождение в диапазон
+(1..8).includes? 2 #=> true
+
+
+# Кортежи
+# Неизменяемые последовательности фиксированного размера, содержащие,
+# как правило, элементы разных типов
+
+{1, "hello", 'x'}.class #=> Tuple(Int32, String, Char)
+
+# Доступ к элементам осуществляется по индексу
+tuple = {:key1, :key2}
+tuple[1] #=> :key2
+tuple[2] #=> syntax error : Index out of bound
+
+# Элементы кортежей можно попарно присвоить переменным
+a, b, c = {:a, 'b', "c"}
+a #=> :a
+b #=> 'b'
+c #=> "c"
+
+
+# Процедуры
+# Указатели на функцию с необязательным содержимым (замыкание).
+# Обычно создаётся с помощью специального литерала ->
+
+proc = ->(x : Int32) { x.to_s }
+proc.class # Proc(Int32, String)
+# Или посредством метода .new
+Proc(Int32, String).new { |x| x.to_s }
+
+# Вызываются посредством метода .call
+proc.call 10 #=> "10"
+
+
+# Управляющие операторы
+
+if true
+ "if statement"
+elsif false
+ "else-if, optional"
+else
+ "else, also optional"
+end
+
+puts "if as a suffix" if true
+
+# if как часть выражения
+a = if 2 > 1
+ 3
+ else
+ 4
+ end
+
+a #=> 3
+
+# Тернарный if
+a = 1 > 2 ? 3 : 4 #=> 4
+
+# Оператор выбора
+cmd = "move"
+
+action = case cmd
+ when "create"
+ "Creating..."
+ when "copy"
+ "Copying..."
+ when "move"
+ "Moving..."
+ when "delete"
+ "Deleting..."
+end
+
+action #=> "Moving..."
+
+
+# Циклы
+
+index = 0
+while index <= 3
+ puts "Index: #{index}"
+ index += 1
+end
+# Index: 0
+# Index: 1
+# Index: 2
+# Index: 3
+
+index = 0
+until index > 3
+ puts "Index: #{index}"
+ index += 1
+end
+# Index: 0
+# Index: 1
+# Index: 2
+# Index: 3
+
+# Но лучше использовать each
+(1..3).each do |index|
+ puts "Index: #{index}"
+end
+# Index: 1
+# Index: 2
+# Index: 3
+
+# Тип переменной зависит от типа выражения
+if a < 3
+ a = "hello"
+else
+ a = true
+end
+typeof a #=> (Bool | String)
+
+if a && b
+ # здесь гарантируется, что и a, и b — не nil
+end
+
+if a.is_a? String
+ a.class #=> String
+end
+
+
+# Методы
+
+def double(x)
+ x * 2
+end
+
+# Методы (а также любые блоки) всегда возвращают значение последнего выражения
+double(2) #=> 4
+
+# Скобки можно опускать, если вызов метода не вносит двусмысленности
+double 3 #=> 6
+
+double double 3 #=> 12
+
+def sum(x, y)
+ x + y
+end
+
+# Параметры методов перечисляются через запятую
+sum 3, 4 #=> 7
+
+sum sum(3, 4), 5 #=> 12
+
+
+# yield
+
+# У всех методов есть неявный необязательный параметр блока, который можно
+# вызвать ключевым словом yield
+
+def surround
+ puts '{'
+ yield
+ puts '}'
+end
+
+surround { puts "hello world" }
+
+# {
+# hello world
+# }
+
+# Методу можно передать блок
+# & — ссылка на переданный блок
+def guests(&block)
+ block.call "some_argument"
+end
+
+# Методу можно передать список параметров, доступ к ним будет как к массиву
+# Для этого используется оператор *
+def guests(*array)
+ array.each { |guest| puts guest }
+end
+
+# Если метод возвращает массив, можно попарно присвоить значение каждого из его
+# элементов переменным
+def foods
+ ["pancake", "sandwich", "quesadilla"]
+end
+breakfast, lunch, dinner = foods
+breakfast #=> "pancake"
+dinner #=> "quesadilla"
+
+# По соглашению название методов, возвращающих булево значение, должно
+# оканчиваться вопросительным знаком
+5.even? # false
+5.odd? # true
+
+# Если название метода оканчивается восклицательным знаком, по соглашению это
+# означает, что метод делает что-то необратимое, например изменяет получателя.
+# Некоторые методы имеют две версии: "опасную" версию с !, которая что-то
+# меняет, и "безопасную", которая просто возвращает новое значение
+company_name = "Dunder Mifflin"
+company_name.gsub "Dunder", "Donald" #=> "Donald Mifflin"
+company_name #=> "Dunder Mifflin"
+company_name.gsub! "Dunder", "Donald"
+company_name #=> "Donald Mifflin"
+
+
+# Классы
+# Определяются с помощью ключевого слова class
+
+class Human
+
+ # Переменная класса является общей для всех экземпляров этого класса
+ @@species = "H. sapiens"
+
+ # Объявление типа переменной name экземпляра класса
+ @name : String
+
+ # Базовый конструктор
+ # Значением первого параметра инициализируем переменную @name.
+ # То же делаем и со вторым параметром — переменная @age. В случае, если мы
+ # не передаём второй параметр, для инициализации @age будет взято значение
+ # по умолчанию (в данном случае — 0)
+ def initialize(@name, @age = 0)
+ end
+
+ # Базовый метод установки значения переменной
+ def name=(name)
+ @name = name
+ end
+
+ # Базовый метод получения значения переменной
+ def name
+ @name
+ end
+
+ # Синтаксический сахар одновременно для двух методов выше
+ property :name
+
+ # А также по отдельности
+ getter :name
+ setter :name
+
+ # Метод класса определяется ключевым словом self, чтобы его можно было
+ # различить с методом экземпляра класса. Такой метод можно вызвать только
+ # на уровне класса, а не экземпляра.
+ def self.say(msg)
+ puts msg
+ end
+
+ def species
+ @@species
+ end
+end
+
+
+# Создание экземпляра класса
+jim = Human.new("Jim Halpert")
+
+dwight = Human.new("Dwight K. Schrute")
+
+# Вызов методов экземпляра класса
+jim.species #=> "H. sapiens"
+jim.name #=> "Jim Halpert"
+jim.name = "Jim Halpert II" #=> "Jim Halpert II"
+jim.name #=> "Jim Halpert II"
+dwight.species #=> "H. sapiens"
+dwight.name #=> "Dwight K. Schrute"
+
+# Вызов метода класса
+Human.say("Hi") #=> выведет "Hi" и вернёт nil
+
+# Переменные экземпляра класса (@) видно только в пределах экземпляра
+class TestClass
+ @var = "I'm an instance var"
+end
+
+# Переменные класса (@) видны как в экземплярах класса, так и в самом классе
+class TestClass
+ @@var = "I'm a class var"
+end
+
+# Переменные с большой буквы — это константы
+Var = "I'm a constant"
+Var = "can't be updated" # Error: already initialized constant Var
+
+# Примеры
+
+# Базовый класс
+class Human
+ @@foo = 0
+
+ def self.foo
+ @@foo
+ end
+
+ def self.foo=(value)
+ @@foo = value
+ end
+end
+
+# Класс-потомок
+class Worker < Human
+end
+
+Human.foo #=> 0
+Worker.foo #=> 0
+
+Human.foo = 2 #=> 2
+Worker.foo #=> 0
+
+Worker.foo = 3 #=> 3
+Human.foo #=> 2
+Worker.foo #=> 3
+
+module ModuleExample
+ def foo
+ "foo"
+ end
+end
+
+# Подключение модуля в класс добавляет его методы в экземпляр класса
+# Расширение модуля добавляет его методы в сам класс
+
+class Person
+ include ModuleExample
+end
+
+class Book
+ extend ModuleExample
+end
+
+Person.foo # => undefined method 'foo' for Person:Class
+Person.new.foo # => 'foo'
+Book.foo # => 'foo'
+Book.new.foo # => undefined method 'foo' for Book
+
+
+# Обработка исключений
+
+# Создание пользовательского типа исключения
+class MyException < Exception
+end
+
+# Ещё одного
+class MyAnotherException < Exception; end
+
+ex = begin
+ raise MyException.new
+rescue ex1 : IndexError
+ "ex1"
+rescue ex2 : MyException | MyAnotherException
+ "ex2"
+rescue ex3 : Exception
+ "ex3"
+rescue ex4 # без указания конкретного типа исключения будут "отлавливаться" все
+ "ex4"
+end
+
+ex #=> "ex2"
+
+```
+
+## Дополнительная информация
+
+### На русском
+
+- [Официальная документация](http://ru.crystal-lang.org/docs/)
+
+### На английском
+
+- [Official Documentation](http://crystal-lang.org/)