puts "Мы в третьем квартале"
when 10..12
puts "Мы в четвертом квартале"
end
Его также можно использовать с типами данных вместо значений или диапазонов:
int_or_string = rand(1..2) == 1 ? 10 : "привет"
case int_or_string
when Int32
puts "Это целое число"
when String
puts "Это строка"
end
Таким образом, интересно использовать оператор case
для проверки других вещей, кроме прямого равенства. Это работает, потому что за кулисами case использует оператор ===
для сравнения целевого значения с каждым предложением if
. Вместо строгого равенства оператор ===
проверяет равенство или совместимость с заданным набором и является более расслабленным.
Как и оператор if
, оператор case
также может иметь ветвь else
, если ни один из параметров не соответствует:
case rand(1..10)
when 1..3
puts "Я кот"
when 4..6
puts "Я собака"
else
puts "Я случайное животное"
end
На данный момент вы научились использовать переменные, вызывать методы и выполнять различные операции с условными выражениями. Но также очень полезно повторять выполнение до тех пор, пока какое-либо условие не станет истинным, например, при поиске данных или преобразовании элементов. Теперь вы узнаете о примитивах, позволяющих сделать именно это.
while и until loops
Оператор while
аналогичен оператору if
, но он повторяется до тех пор, пока условие не станет ложным. Посмотрите это, например:
secret_number = rand(1..5)
print "Пожалуйста, введите ваше предположение: "
guess = read_line.to_i
while guess != secret_number
puts "Извините, это не то. Пожалуйста, попробуйте еще раз: "
guess = read_line.to_i
end
puts "Вы правильно угадали!"
Аналогично, оператор until
является противоположностью оператора while
, так же, как оператор unless
является противоположностью оператора if
:
secret_number = rand(1..5)
print "Пожалуйста, введите ваше предположение: "
guess = read_line.to_i
until guess == secret_number
puts "Извините, это не то. Пожалуйста, попробуйте еще раз: "
guess = read_line.to_i
end
puts "Вы правильно угадали!"
Внутри циклической структуры вы можете использовать следующие дополнительные ключевые слова:
• break
— немедленно прерывает цикл и выходит из него без повторной проверки условия.
• next
— прерывает текущее выполнение цикла и начинает заново с начала, проверяя условие
Вот пример использования break
и next
для дальнейшего управления потоком:
secret_number = rand(1..5)
while true
print "Пожалуйста, введите свое предположение (ноль, чтобы отказаться): "
guess = read_line.to_i
if guess < 0 || guess > 5
puts "Неверное предположение. Пожалуйста, попробуйте еще раз."
next
end
if guess == 0
puts "Извините, вы сдались. Ответ был #{secret_number}."
break
elsif guess == secret_number
puts "Поздравляем! Вы угадали секретный номер!"
break
end
puts "Извините, это не то. Пожалуйста, попробуйте еще раз."
end
Они составляют основу управления потоком выполнения с использованием условий и структуры цикла. Далее в этой главе вы также узнаете о блоках — наиболее распространенном способе создания циклов в Crystal, особенно с контейнерами данных. Но перед этим давайте углубимся в систему типов.
Изучение системы типов
Crystal — статически типизированный язык; компилятор знает типы каждой переменной и выражения перед выполнением. Это позволяет выполнить несколько проверок правильности вашего кода, например проверить существование вызванных методов и соответствие переданных аргументов сигнатуре или убедиться, что вы не пытаетесь получить доступ к нулевым свойствам.
Одного типа недостаточно в каждой ситуации: одну переменную можно переназначить значениям разных типов, и, таким образом, тип переменной может быть любым из типов каждого значения. Это можно выразить с помощью типа объединения, типа, созданного путем объединения всех возможных типов. Благодаря этому компилятор знает, что переменная может содержать значение любого из этих типов во время выполнения.
Вы можете использовать оператор typeof(x)
, чтобы определить тип любого выражения или переменной, видимый компилятором. Это может быть объединение нескольких типов. Вы также можете использовать x.class
для определения типа значения во время выполнения; это никогда не будет союзом. Наконец, существует оператор x.is_a?(Type)
, позволяющий проверить, принадлежит ли что-либо заданному типу, что полезно для разветвления и выполнения действий по-разному. Ниже приведены некоторые примеры: