Поток управления определяет порядок выполнения вашей программы. Топаз предоставляет мощные и выразительные структуры потока управления. 🎯
🔀 Условные операторы
Операторы if
let возраст = 25
let оценка = 85
// Базовый оператор if
if возраст >= 18 {
print("Вы совершеннолетний")
}
// Оператор if-else
if оценка >= 90 {
print("Оценка A")
} else {
print("Нужно больше стараться")
}
// Цепочка if-else if
if оценка >= 90 {
print("Оценка A - Отлично")
} else if оценка >= 80 {
print("Оценка B - Хорошо")
} else if оценка >= 70 {
print("Оценка C - Удовлетворительно")
} else {
print("Требуется пересдача")
}
// Составные условия
let имяПользователя = "ТопазДев"
let попытки = 3
if имяПользователя.length() > 0 && попытки < 5 {
print("Вы можете попытаться войти в систему")
}
Условные выражения
// Вместо ?: используйте if как выражение (v3)
let статусВзрослости = if возраст >= 18 { "взрослый" } else { "несовершеннолетний" }
let статусСдачи = if оценка >= 60 { "сдал" } else { "не сдал" }
// Вложенные условия
let буквеннаяОценка = if оценка >= 90 { "A" }
else if оценка >= 80 { "B" }
else if оценка >= 70 { "C" }
else { "F" }
// Условное значение
let скидка = if уровеньЧленства == "VIP" { 0.2 }
else if уровеньЧленства == "Золото" { 0.1 }
else { 0.05 }
print("Возраст: {возраст}, Статус: {статусВзрослости}")
print("Оценка: {оценка}, Буквенная оценка: {буквеннаяОценка}")
if как выражение
// Использование if как выражения
let сообщение = if время < 12 {
"Доброе утро!"
} else if время < 18 {
"Добрый день!"
} else {
"Добрый вечер!"
}
// Сложное условное вычисление
let стоимостьДоставки = if суммаЗаказа >= 50000 {
0
} else if расстояние <= 10 {
3000
} else {
5000
}
print(сообщение)
print("Стоимость доставки: {стоимостьДоставки} рублей")
🔄 Циклы
Циклы for
// Цикл for с диапазоном
for i in 0..5 {
print("Итерация {i}")
}
// Включающий диапазон
for i in 1..=10 {
print("Число: {i}")
}
// Итерация по массиву
let фрукты = ["яблоко", "банан", "апельсин", "виноград"]
for фрукт in фрукты {
print("Фрукт: {фрукт}")
}
// Итерация с индексом и значением
for (индекс, фрукт) in фрукты.enumerate() {
print("{индекс}: {фрукт}")
}
// Итерация по ключ-значение объекта
let информацияПользователя = {
имя: "ТопазДев",
возраст: 25,
работа: "разработчик"
}
for (ключ, значение) in информацияПользователя {
print("{ключ}: {значение}")
}
// Итерация с шагом
for i in (0..20).step(2) {
print("Четное: {i}")
}
Циклы while
// Базовый цикл while
let mut счетчик = 0
while счетчик < 5 {
print("Счетчик: {счетчик}")
счетчик += 1
}
// Условный цикл while
let mut ввод = ""
while ввод != "выход" {
ввод = input("Введите команду (наберите 'выход' для завершения): ")
if ввод != "выход" {
print("Получена команда: {ввод}")
}
}
// Бесконечный цикл (с break)
let mut попытки = 0
while true {
попытки += 1
let успех = Math.random() > 0.8
if успех {
print("Успех! После {попытки} попыток")
break
}
if попытки >= 10 {
print("Превышено максимальное количество попыток")
break
}
}
Управление циклами
// break и continue
for i in 1..=20 {
if i % 3 == 0 && i % 5 == 0 {
print("{i}: FizzBuzz")
continue
}
if i % 3 == 0 {
print("{i}: Fizz")
continue
}
if i % 5 == 0 {
print("{i}: Buzz")
continue
}
if i > 15 {
print("Превышено 15, остановка")
break
}
print("{i}")
}
// Меченые циклы
внешний: for i in 1..=3 {
for j in 1..=3 {
if i * j > 6 {
print("Произведение превышает 6, прерывание внешнего цикла")
break внешний
}
print("{i} × {j} = {i * j}")
}
}
🎭 Сопоставление образцов (match)
Базовый оператор match
let деньНедели = "понедельник"
match деньНедели {
case "понедельник" => print("Начало недели!")
case "пятница" => print("Слава пятнице!")
case "суббота" | "воскресенье" => print("Выходные!")
case _ => print("Обычный день")
}
// match, возвращающий значение
let типДня = match деньНедели {
case "понедельник" | "вторник" | "среда" | "четверг" | "пятница" => "рабочий день"
case "суббота" | "воскресенье" => "выходной"
case _ => "неизвестно"
}
print("Сегодня {типДня}")
Сопоставление чисел
let оценка = 87
let буквеннаяОценка = match оценка {
case 90..=100 => "A"
case 80..=89 => "B"
case 70..=79 => "C"
case 60..=69 => "D"
case _ => "F"
}
// Использование условий-ограждений
let评价 = match оценка {
case x if x >= 95 => "Идеальный результат!"
case x if x >= 90 => "Отличная работа"
case x if x >= 80 => "Хороший результат"
case x if x >= 70 => "Средний уровень"
case x if x >= 60 => "Сдано"
case _ => "Требуется пересдача"
}
print("Оценка: {оценка}, Буквенная оценка: {буквеннаяОценка}, Оценка: {评价}")
Сопоставление структур/объектов
let пользователь = {
имя: "ТопазДев",
возраст: 25,
работа: "разработчик",
местоположение: "Москва"
}
// Деструктурирующее сопоставление
match пользователь {
case { имя: "ТопазДев", возраст, работа: "разработчик" } => {
print("Разработчик на Топазе, возраст: {возраст}")
}
case { возраст: пользовательскийВозраст, местоположение: "Москва" } if пользовательскийВозраст < 30 => {
print("Молодой пользователь в Москве")
}
case { работа: "разработчик", местоположение } => {
print("Разработчик в {местоположение}")
}
case _ => {
print("Обычный пользователь")
}
}
// Сопоставление вложенных объектов
let заказ = {
клиент: { имя: "ПользовательТопаз", vip: true },
товары: ["ноутбук", "мышь"],
общаяСумма: 1500000
}
match заказ {
case { клиент: { vip: true }, общаяСумма: сумма } if сумма > 1000000 => {
print("Крупный заказ VIP-клиента: {сумма} рублей")
}
case { клиент: { имя }, товары } if товары.length() > 1 => {
print("Заказ {имя} с несколькими товарами")
}
case _ => {
print("Обычный заказ")
}
}
Сопоставление массивов
let числа = [1, 2, 3, 4, 5]
match числа {
case [] => print("Пустой массив")
case [первый] => print("Один элемент: {первый}")
case [первый, второй] => print("Два элемента: {первый}, {второй}")
case [первый, ...остальные] => {
print("Первый: {первый}, Остальные: {остальные}")
}
}
// Специфичное сопоставление образцов
let списокОценок = [95, 87, 92]
match списокОценок {
case [100, ...] => print("Начинается с идеальной оценки!")
case [..., 100] => print("Заканчивается идеальной оценкой!")
case [a, b, c] if a > 90 && b > 90 && c > 90 => print("Все оценки выше 90!")
case оценки if оценки.all(x => x >= 80) => print("Все оценки выше 80")
case _ => print("Обычное распределение оценок")
}
Сопоставление перечислений (enum)
enum Статус {
Ожидание,
Обработка(прогресс: int),
Завершено(результат: string),
Ошибка(сообщение: string)
}
let текущийСтатус = Статус.Обработка(прогресс: 75)
match текущийСтатус {
case Статус.Ожидание => print("Ожидание...")
case Статус.Обработка(прогресс: прогресс) => {
print("Обработка: {прогресс}%")
if прогресс > 50 {
print("Более половины выполнено")
}
}
case Статус.Завершено(результат: результат) => print("Завершено: {результат}")
case Статус.Ошибка(сообщение: ошибка) => print("Произошла ошибка: {ошибка}")
}
// Сопоставление типа Option
let опциональноеЗначение: Option<string> = Some("Топаз")
match опциональноеЗначение {
case Some(значение) => print("Имеет значение: {значение}")
case None => print("Нет значения")
}
// Сопоставление типа Result
function разделить(a: int, b: int) -> Result<int, string> {
if b == 0 {
return Err("Нельзя делить на ноль")
}
return Ok(a / b)
}
match разделить(10, 2) {
case Ok(результат) => print("Результат деления: {результат}")
case Err(ошибка) => print("Ошибка: {ошибка}")
}
🛡️ Условия-ограждения и продвинутые образцы
Сложные условия-ограждения
let температура = 25
let влажность = 60
let сезон = "лето"
match (температура, влажность, сезон) {
case (t, h, "лето") if t > 30 && h > 70 => print("Очень жарко и влажно")
case (t, h, "лето") if t > 25 && h < 50 => print("Тепло и сухо")
case (t, _, "зима") if t < 0 => print("Очень холодно")
case (t, h, _) if t >= 20 && t <= 25 && h >= 40 && h <= 60 => print("Приятная погода")
case _ => print("Обычная погода")
}
Функциональное сопоставление образцов
// Рекурсивное сопоставление образцов для обработки списка
function суммаСписка(список: [int]) -> int {
match список {
case [] => 0
case [первый, ...остальные] => первый + суммаСписка(остальные)
}
}
// Обход бинарного дерева
enum Дерево<T> {
Пустое,
Узел(значение: T, левое: Дерево<T>, правое: Дерево<T>)
}
function обходДерева<T>(дерево: Дерево<T>) {
match дерево {
case Дерево.Пустое => {
// Ничего не делаем
}
case Дерево.Узел(значение: значение, левое: левое, правое: правое) => {
обходДерева(левое)
print("Значение узла: {значение}")
обходДерева(правое)
}
}
}
print("Сумма списка: {суммаСписка([1, 2, 3, 4, 5])}") // 15
⚡ Продвинутые образцы потока управления
Комбинирование циклов с сопоставлением образцов
let списокЗадач = [
{ тип: "email", приоритет: 1, содержание: "Проверить расписание встреч" },
{ тип: "звонок", приоритет: 3, содержание: "Консультация клиента" },
{ тип: "документ", приоритет: 2, содержание: "Написать отчет" }
]
for задача in списокЗадач {
match задача {
case { тип: "email", приоритет: 1, содержание } => {
print("Срочная обработка email: {содержание}")
}
case { тип: типЗадачи, приоритет, содержание } if приоритет <= 2 => {
print("Важная задача {типЗадачи}: {содержание}")
}
case { тип, содержание } => {
print("Обычная задача {тип}: {содержание}")
}
}
}
Обработка ошибок и поток управления
// Обработка ошибок в стиле try-catch
function безопасноеЧтениеФайла(имяФайла: string) -> Result<string, string> {
if !имяФайла.endsWith(".txt") {
return Err("Поддерживаются только текстовые файлы")
}
// Симуляция чтения файла
if Math.random() > 0.7 {
return Err("Файл не найден")
}
return Ok("Содержимое файла здесь")
}
// Поток управления с обработкой ошибок
for имяФайла in ["data.txt", "config.json", "readme.txt"] {
match безопасноеЧтениеФайла(имяФайла) {
case Ok(содержимое) => {
print("Успешно прочитан: {имяФайла}")
print("Содержимое: {содержимое}")
// Продолжить к следующему файлу при успехе
}
case Err(сообщениеОшибки) => {
print("Ошибка ({имяФайла}): {сообщениеОшибки}")
if сообщениеОшибки.contains("поддерживаются") {
print("Неподдерживаемый формат файла, пропускаем")
continue // Продолжить к следующему файлу
} else {
print("Критическая ошибка, остановка обработки")
break // Остановить всю обработку
}
}
}
}
Цепочки условного выполнения
// Условное связывание
function обработатьПользователя(идПользователя: int) -> Result<string, string> {
let данныеПользователя = match получитьПользователяИзБазы(идПользователя) {
case Ok(данные) => данные
case Err(ошибка) => return Err("Не удалось получить пользователя: {ошибка}")
}
let результатВалидации = match валидироватьПользователя(данныеПользователя) {
case Ok(_) => ()
case Err(ошибка) => return Err("Валидация не пройдена: {ошибка}")
}
let результатОбработки = match обработатьДанныеПользователя(данныеПользователя) {
case Ok(результат) => результат
case Err(ошибка) => return Err("Обработка не удалась: {ошибка}")
}
return Ok("Обработка завершена: {результатОбработки}")
}
// Монадический стиль связывания
function монадическаяОбработка(идПользователя: int) -> Result<string, string> {
return получитьПользователяИзБазы(идПользователя)
.andThen(валидироватьПользователя)
.andThen(обработатьДанныеПользователя)
.map(результат => "Обработка завершена: {результат}")
}
🎯 Оптимизация и лучшие практики
1. Оптимизация условных операторов
// Плохо: Вложенные условия
let оценка = 85
if оценка >= 90 {
print("Оценка A")
} else {
if оценка >= 80 {
print("Оценка B")
} else {
if оценка >= 70 {
print("Оценка C")
} else {
print("Оценка F")
}
}
}
// Хорошо: Использование match
let буквеннаяОценка = match оценка {
case 90..=100 => "A"
case 80..=89 => "B"
case 70..=79 => "C"
case _ => "F"
}
print("Оценка {буквеннаяОценка}")
2. Образец раннего возврата
function зарегистрироватьПользователя(имя: string, email: string, возраст: int) -> Result<string, string> {
// Ранняя валидация и возврат
if имя.length() == 0 {
return Err("Требуется имя")
}
if !email.contains("@") {
return Err("Требуется действительный email")
}
if возраст < 0 || возраст > 120 {
return Err("Требуется действительный возраст")
}
// Обработка только при прохождении всех валидаций
let пользователь = создатьНовогоПользователя(имя, email, возраст)
return Ok("Регистрация пользователя завершена: {пользователь.id}")
}
3. Использование сопоставления образцов
// Выражение сложной бизнес-логики с помощью образцов
enum СтатусЗаказа {
Создан,
ОплатаЗавершена,
Доставка,
Доставлен,
Отменен
}
function обработатьЗаказ(статус: СтатусЗаказа, суммаОплаты: int, этоVip: bool) -> string {
match (статус, суммаОплаты, этоVip) {
case (СтатусЗаказа.Создан, _, _) => "Пожалуйста, проведите оплату"
case (СтатусЗаказа.ОплатаЗавершена, сумма, true) if сумма > 100000 => {
"Подготовка экспресс-доставки для VIP-клиента"
}
case (СтатусЗаказа.ОплатаЗавершена, сумма, _) if сумма > 50000 => {
"Подготовка обычной доставки"
}
case (СтатусЗаказа.ОплатаЗавершена, _, _) => "Подготовка стандартной доставки"
case (СтатусЗаказа.Доставка, _, true) => "Служба отслеживания VIP-доставки"
case (СтатусЗаказа.Доставка, _, _) => "В доставке"
case (СтатусЗаказа.Доставлен, _, _) => "Доставка завершена"
case (СтатусЗаказа.Отменен, _, _) => "Заказ отменен"
}
}
Поток управления Топаз мощный и выразительный. Правильно комбинируйте условные операторы, циклы и сопоставление образцов, чтобы писать читаемый и поддерживаемый код! 🚀