Топаз предоставляет различные операторы для манипулирования и вычисления данных. Понимание точного поведения и приоритета всех операторов является критически важным. ⚡
🔢 Арифметические операторы
Базовые арифметические операции
// Основные арифметические операторы
let число1 = 10
let число2 = 3
let сложение = число1 + число2 // 13
let вычитание = число1 - число2 // 7
let умножение = число1 * число2 // 30
let деление = число1 / число2 // 3.333...
let остаток = число1 % число2 // 1
let возведение = число1 ** число2 // 1000
print("Сложение: {сложение}")
print("Вычитание: {вычитание}")
print("Умножение: {умножение}")
print("Деление: {деление}")
print("Остаток: {остаток}")
print("Возведение в степень: {возведение}")
Унарные операторы
let положительное = +42 // 42 (явно положительное)
let отрицательное = -42 // -42 (отрицание)
let число = 15
let обращённое = -число // -15
print("Исходное значение: {число}")
print("Обращённое: {обращённое}")
Операторы инкремента/декремента
let mut счётчик = 5
счётчик = счётчик + 1
счётчик = счётчик - 1
function увеличить(значение: int) -> int { значение + 1 }
function уменьшить(значение: int) -> int { значение - 1 }
счётчик = увеличить(счётчик)
счётчик = уменьшить(счётчик)
print("Итоговое значение счётчика: {счётчик}")
Составные операторы присваивания
let mut значение = 10
значение += 5 // значение = значение + 5 = 15
значение -= 3 // значение = значение - 3 = 12
значение *= 2 // значение = значение * 2 = 24
значение /= 4 // значение = значение / 4 = 6
значение %= 4 // значение = значение % 4 = 2
значение **= 3 // значение = значение ** 3 = 8
print("Итоговое значение: {значение}")
🔍 Операторы сравнения
Базовые сравнения
let икс = 10
let игрек = 20
let зет = 10
// Сравнение на равенство
let равно = икс == зет // true
let неРавно = икс != игрек // true
// Сравнение размера
let меньше = икс < игрек // true
let меньшеИлиРавно = икс <= зет // true
let больше = игрек > икс // true
let большеИлиРавно = зет >= икс // true
print("икс == зет: {равно}")
print("икс != игрек: {неРавно}")
print("икс < игрек: {меньше}")
print("игрек > икс: {больше}")
Типобезопасное сравнение
// Топаз обеспечивает типобезопасное сравнение
let целое = 42
let вещественное = 42.0
let строка = "42"
// Только одинаковые типы можно сравнивать
let сравнениеЦелых = целое == 42 // true
let сравнениеВещественных = вещественное == 42.0 // true
// Сравнение разных типов требует явного преобразования
let сравнениеСтрок = целое.toString() == строка // true
let сравнениеЧисел = целое == parseInt(строка) // true
print("Сравнение с преобразованием типа: {сравнениеСтрок}")
Специальные операторы сравнения
Топаз v4 не включает оператор <=> (spaceship).
🧠 Логические операторы
Базовые логические операции
let истина = true
let ложь = false
// Логическое И
let результатИ = истина && ложь // false
let результатИ2 = истина && истина // true
// Логическое ИЛИ
let результатИли = истина || ложь // true
let результатИли2 = ложь || ложь // false
// Логическое НЕ
let результатНе = !истина // false
let результатНе2 = !ложь // true
print("Результат И: {результатИ}")
print("Результат ИЛИ: {результатИли}")
print("Результат НЕ: {результатНе}")
Короткое замыкание
function функцияСПобочнымЭффектом() -> bool {
print("Функция была вызвана!")
return true
}
// Короткое замыкание И - второе не выполняется, если первое false
let короткоеИ = false && функцияСПобочнымЭффектом() // Функция не вызвана
// Короткое замыкание ИЛИ - второе не выполняется, если первое true
let короткоеИли = true || функцияСПобочнымЭффектом() // Функция не вызвана
print("Короткое И: {короткоеИ}")
print("Короткое ИЛИ: {короткоеИли}")
Оператор объединения с null
// Оператор объединения с null (??)
let значение1: Option<string> = None
let значение2: Option<string> = Some("по умолчанию")
let значение3 = "резервное"
let результат1 = значение1 ?? "ничего" // "ничего"
let результат2 = значение2 ?? "ничего" // "по умолчанию"
let результат3 = значение1 ?? значение2 ?? значение3 // "по умолчанию"
print("Результат объединения с null: {результат1}")
// С Option
let пользователь = { имя: "РазработчикТопаз", возраст: Some(25) }
let возраст = match пользователь.возраст { case Some(v) => v; case None => 0 }
print("Возраст: {возраст}")
Присваивание объединения с null (??=)
Оператор присваивания, который инициализирует переменную только если она сейчас None/null. Это оператор‑оператор на уровне оператора (statement‑only): не возвращает значение выражения. Правоассоциативный.
let mut name: Option<string> = None
name ??= Some("guest") // name станет Some("guest")
name ??= Some("override") // без изменений (уже Some)
// Правоассоциативность
a ??= b ??= Some(1) // то же, что: a ??= (b ??= Some(1))
🔧 Побитовые/сдвиговые операторы
В Топазе v4 побитовые и сдвиговые операторы отсутствуют. Обратите внимание, что >> зарезервирован под композицию функций (а не битовый сдвиг). См. раздел о композиции ниже.
🎯 Специальные операторы
Операторы типов
В Топазе v4 отсутствуют typeof и instanceof. Для определения типа используйте сопоставление образцов или утилиты стандартной библиотеки.
Операторы диапазона
// Диапазоны: .. (включительно), ..< (верхняя граница исключена)
let включительно = 1..5 // 1, 2, 3, 4, 5
let исключаяВерхнюю = 1..<5 // 1, 2, 3, 4
for x in включительно { print(x) }
for x in исключаяВерхнюю { print(x) }
Оператор принадлежности (in)
// Массивы/Списки/Множества
let ok1 = 3 in [1, 2, 3] // true
let ok2 = "a" in Set.of("a", "b") // true
// Ключи map (через представление keys)
let hasId = "id" in userMap.keys // bool
// Диапазоны
let inside = 5 in 1..10 // true
let outside = 10 in 1..<10 // false
Оператор распространения
В синтаксис Топаза v4 не входит.
Опциональная цепочка (?.)
Только для Option/nullable. Парсится, когда слева Option<T> или объединение с null (например, T | null). Это не общий объектный чейнинг; для обычного доступа используйте ..
let user: Option<{ name: string, profile: Option<{ city: string }> }> =
Some({ name: "Ann", profile: Some({ city: "Seoul" }) })
let nameOpt = user?.name // Option<string>
let cityOpt = user?.profile?.city // Option<string>
let city = user?.profile?.city ?? "Unknown" // string
let noneUser: Option<{ name: string }> = None
let fallback = noneUser?.name ?? "guest" // "guest"
// Сводится к цепочке Option.map/flatMap
Оператор конвейера
// Оператор конвейера (|>)
let результат = 10
|> (х => х * 2) // 20
|> (х => х + 5) // 25
|> (х => х.toString()) // "25"
// Полезно для цепочки функций
let данные = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|> (масс => масс.filter(х => х % 2 == 0)) // [2, 4, 6, 8, 10]
|> (масс => масс.map(х => х * х)) // [4, 16, 36, 64, 100]
|> (масс => масс.reduce((а, б) => а + б)) // 220
print("Результат конвейера: {результат}")
print("Результат цепочки: {данные}")
⚡ Приоритет операторов (Топаз v4)
v4// Высокий → Низкий; ассоциативность указана
1) Вызов/Индекс/Доступ: () [] . ?. (левый)
2) Возведение в степень: ** (правый)
3) Унарные: + - ! (правый)
4) Умножение/Деление/Остаток: * / % (левый)
5) Сложение/Вычитание: + - (левый)
6) Диапазон: .. ..< (левый) // ниже арифметики, выше сравнений
7) Сравнения: < <= > >= == != in (левый)
8) Логическое И: && (левый)
9) Логическое ИЛИ: || (левый)
10) Объединение с null: ?? (левый)
11) Композиция функций: >> (правый)
12) Конвейер: |> (левый)
13) Присваивание: = …, ??= (правый)
// >> выше |> (|> ниже >>)
let h = f >> g
let x = вход |> h // т.е. вход |> (f >> g)
Композиция функций (>>)
let нормализация = trim >> toLowerCase >> collapseSpaces
print(нормализация(" Hello WORLD ")) // "hello world"
🔄 Перегрузка операторов
Операторы для пользовательских типов
// Реализация операторов для структур
struct Вектор {
x: float,
y: float
}
impl Вектор {
// Перегрузка оператора +
function +(другой: Вектор) -> Вектор {
return Вектор { x: self.x + другой.x, y: self.y + другой.y }
}
// Перегрузка оператора * (скалярное умножение)
function *(скаляр: float) -> Вектор {
return Вектор { x: self.x * скаляр, y: self.y * скаляр }
}
// Перегрузка оператора ==
function ==(другой: Вектор) -> bool {
return self.x == другой.x && self.y == другой.y
}
// Преобразование в строку
function toString() -> string {
return "Вектор({self.x}, {self.y})"
}
}
// Примеры использования
let вектор1 = Вектор { x: 3.0, y: 4.0 }
let вектор2 = Вектор { x: 1.0, y: 2.0 }
let сумма = вектор1 + вектор2 // Вектор(4.0, 6.0)
let масштабированный = вектор1 * 2.0 // Вектор(6.0, 8.0)
let равны = вектор1 == вектор2 // false
print("Сумма векторов: {сумма}")
print("Масштабированный вектор: {масштабированный}")
print("Векторы равны: {равны}")
🛡️ Безопасное использование операторов
1. Обработка переполнения
// Проверяемые арифметические операции
let большоеЧисло1 = 2147483647 // максимальное значение int
let большоеЧисло2 = 1
// Безопасное сложение (проверка переполнения)
match большоеЧисло1.checkedAdd(большоеЧисло2) {
case Some(результат) => print("Безопасное сложение: {результат}")
case None => print("Произошло переполнение!")
}
// Насыщающие операции (ограничение до макс/мин значений)
let насыщающееСложение = большоеЧисло1.saturatingAdd(большоеЧисло2) // остаётся на макс int
print("Насыщающее сложение: {насыщающееСложение}")
2. Предотвращение деления на ноль
function безопасноеДеление(числитель: float, знаменатель: float) -> Result<float, string> {
if знаменатель == 0.0 {
return Err("Нельзя делить на ноль")
}
return Ok(числитель / знаменатель)
}
// Пример использования
match безопасноеДеление(10.0, 0.0) {
case Ok(результат) => print("Результат деления: {результат}")
case Err(ошибка) => print("Ошибка: {ошибка}")
}
3. Типобезопасность
// Обеспечение безопасности явным преобразованием типов
let строковоеЧисло = "123"
let настоящееЧисло = match parseInt(строковоеЧисло) {
case Ok(число) => число
case Err(_) => {
print("Преобразование числа не удалось")
0 // значение по умолчанию
}
}
let результат = настоящееЧисло + 100
print("Результат безопасного вычисления: {результат}")
📊 Советы по оптимизации производительности
1. Оптимизация дорогих операций
// Используйте умножение вместо возведения в степень (для малых степеней)
let квадрат = значение * значение // вместо значение ** 2
let куб = значение * значение * значение // вместо значение ** 3
// Используйте умножение вместо деления
let половина = значение * 0.5 // вместо значение / 2
// Оптимизируйте операции остатка (степени 2)
let остаток = значение & 7 // вместо значение % 8 (8 = 2^3)
2. Используйте короткое замыкание
// Размещайте дорогие вызовы функций позже
let результат = простоеУсловие() && дорогаяФункция()
// Оптимизируйте проверки на null
let значение = объект?.свойство?.подСвойство ?? значениеПоУмолчанию
Понимание и правильное использование операторов Топазе позволяет вам писать эффективный и безопасный код! Всегда помните о приоритете операторов и типобезопасности. 🎯