Шрифт:
Интервал:
Закладка:
msg = if !guess.in? 1..5
"Пожалуйста, введите число от 1 до 5."
elsif guess == secret_number
"Вы правильно угадали!"
else
"Извините, номер был #{secret_number}."
end
puts msg
Это может быть полезно, чтобы избежать повторения или выполнить сложную логику внутри другого выражения. Существует также сокращенная версия, если использовать условие ? истинное утверждение : структура ложного утверждения. Это часто называют тройным:
puts "Вы догадались #{guess == secret_number ? "правильно" : "неправильно"}!"
Часто вы не смотрите на проверку условных операторов, а вместо этого выбираете один из нескольких вариантов. Здесь на помощь приходит оператор case, объединяющий длинную последовательность операторов if.
case
case похож на оператор if, но позволяет определить несколько возможных результатов в зависимости от заданного значения. Вы указываете оператор case с некоторым значением и одним или несколькими вариантами, проверяющими различные возможности. Вот структура:
case Time.local.month
when 1, 2, 3
puts "Мы в первом квартале"
when 4, 5, 6
puts "Мы во втором квартале"
when 7, 8, 9
puts "Мы в третьем квартале"
when 10, 11, 12
puts "Мы в четвертом квартале"
end
Это прямой эквивалент гораздо более длинной и менее читаемой последовательности операторов if:
month = Time.local.month
if month == 1 || month == 2 || month == 3
puts "Мы в первом квартале"
elsif month == 4 || month == 5 || month == 6
puts "Мы во втором квартале"
elsif month == 7 || month == 8 || month == 9
puts "Мы в третьем квартале"
elsif month == 10 || month == 11 || month == 12
puts "Мы в четвертом квартале"
end
Оператор case также можно использовать с диапазонами:
case Time.local.month
when 1..3
puts "Мы в первом квартале"
when 4..6
puts "Мы во втором квартале"
when 7..9
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), чтобы определить тип любого выражения или переменной, видимый компилятором. Это может быть объединение нескольких типов. Вы также можете использовать