Примечание об именах библиотек: Helper-имена вне минимума стандартной библиотеки (
простоеУсловие,дорогаяФункция,userMap) являются иллюстративными placeholders, а не каноническими API.
Топаз предоставляет различные операторы для манипулирования и вычисления данных. Понимание точного поведения и приоритета всех операторов является критически важным.
Арифметические операторы
Базовые арифметические операции
// Основные арифметические операторы
let число1 = 10
let число2 = 3
let сложение = число1 + число2 // 13
let вычитание = число1 - число2 // 7
let умножение = число1 * число2 // 30
let деление = число1 / число2 // 3 — целочисленное деление усекается к нулю
let остаток = число1 % число2 // 1
let возведение = число1 ** число2 // 1000
// float-арифметика остаётся в float-домене (без неявного смешивания)
let отношение = 10.0 / 3.0 // 3.333...
print("Сложение: {сложение}")
print("Вычитание: {вычитание}")
print("Умножение: {умножение}")
print("Деление: {деление}")
print("Остаток: {остаток}")
print("Возведение в степень: {возведение}")Унарные операторы
let положительное = +42 // 42 (явно положительное)
let отрицательное = -42 // -42 (отрицание)
let число = 15
let обращённое = -число // -15
print("Исходное значение: {число}")
print("Обращённое: {обращённое}")Операторы инкремента/декремента
Topaz v5.2 не задаёт сокращённые операторы инкремента или декремента. Используйте явное переприсваивание с let mut.
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
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 сравнениеСтрок = "{целое}" == текст // true
let сравнениеЧисел = match toInt(текст) { // toInt возвращает Option<int>
case Some(значение) => целое == значение
case None => false
}
print("Сравнение с преобразованием типа: {сравнениеСтрок}")Специальные операторы сравнения
Topaz v5.2 не включает оператор <=> (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
a ?? b вычисляется как a, если a не является None и не является null; иначе вычисляется b.
// Оператор объединения с null (??)
let имя: string | null = null
let отображаемоеИмя = имя ?? "guest"
print("Отображаемое имя: {отображаемоеИмя}")
let пользователь: Option<{ имя: string, профиль: Option<{ город: string }> }> =
Some({ имя: "РазработчикТопаз", профиль: Some({ город: "Seoul" }) })
let город = пользователь?.профиль?.город ?? "Unknown"
print("Город: {город}")
let возрастОпция: Option<int> = 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)Побитовые/сдвиговые операторы
Topaz v5.2 не задаёт побитовые и сдвиговые операторы. (Токен, используемый в других языках для сдвигов, зарезервирован под иную цель уровня SPEC, см. примечание под приоритетом операторов.)
Специальные операторы
Операторы типов
В Topaz v5.2 отсутствуют typeof и instanceof. Для сужения типа используйте match с типовыми образцами (см. страницу управления потоком).
Операторы диапазона
// Диапазоны: .. (включительно), ..< (верхняя граница исключена)
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Обновление записей и вариативные параметры
Topaz v5.2 не использует JavaScript-подобный object spread для записей. Для существующих записей используйте синтаксис обновления записи. (Spread массивов ...expr в литералах массивов и в вариативных хвостах вызовов каноничен, см. страницу функций.)
let пользователь = { имя: "Ann", возраст: 30 }
let старшийПользователь = пользователь{ возраст: 31 }
function сумма(...числа: int) -> int {
let mut итог = 0
for число in числа {
итог += число
}
итог
}Маркер ... каноничен для вариативных параметров, например ...числа: int.
Опциональная цепочка (?.)
Только для 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 mapping/flat-mapping или эквивалентным nullable-проверкамОператор конвейера
// Оператор конвейера (|>)
let результат = 10
|> (х => х * 2) // 20
|> (х => х + 5) // 25
|> (х => "{х}") // "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(_, 0, (а, б) => а + б) // 220
print("Результат конвейера: {результат}")
print("Результат цепочки: {данные}")Приоритет операторов
Операторы перечислены от высшего приоритета к низшему:
| Уровень | Операторы | Ассоциативность |
| --- | --- | --- |
| 1 | вызовы, индексация, доступ к членам, опциональный доступ, распространение результата: () [] . ?. постфиксный ? | левая |
| 2 | возведение в степень: ** | правая |
| 3 | унарные: + - ! ~ | правая |
| 4 | мультипликативные: * / % | левая |
| 5 | аддитивные: + - | левая |
| 6 | диапазон: .. ..< | левая |
| 7 | сравнение и принадлежность: < <= > >= == != in | левая |
| 8 | логическое И: && | левая |
| 9 | логическое ИЛИ: \|\| | левая |
| 10 | объединение с null: ?? | левая |
| 11 | конвейер: \|> | левая |
Формы присваивания (=, +=, -=, *=, /=, %=, ??=) — это операторы-statements, а не выражения: они не участвуют в приоритете выражений и не производят значений. Оператор композиции уровня SPEC (>>) занимает уровень приоритета между ?? и |>, но не входит ни в одну текущую поверхность profile; публичные примеры составляют функции через конвейеры |> или лямбды-обёртки.
// |> связывает слабее всех, поэтому арифметика выполняется первой
let удвоить = (х: int) => х * 2
let результатКонвейера = 3 + 2 |> удвоить() // 10 — то же, что (3 + 2) |> удвоить()
// Приоритет диапазона: аддитивные связывают раньше ..
let диапазон = (1 + 0)..(5 - 0)
let внутри = 3 in диапазон // trueHelper-функции для пользовательских типов
Topaz v5.2 не задаёт перегрузку операторов. Используйте явные helper-функции для операций с пользовательскими типами.
// В canonical-документации семантику операторов показывают через явные helper-функции
type Вектор = { x: float, y: float }
function сложитьВекторы(левый: Вектор, правый: Вектор) -> Вектор {
return { x: левый.x + правый.x, y: левый.y + правый.y }
}
function масштабироватьВектор(вектор: Вектор, скаляр: float) -> Вектор {
return { x: вектор.x * скаляр, y: вектор.y * скаляр }
}
function равныВекторы(левый: Вектор, правый: Вектор) -> bool {
return левый.x == правый.x && левый.y == правый.y
}
function векторВСтроку(вектор: Вектор) -> string {
return "Вектор({вектор.x}, {вектор.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. Предотвращение деления на ноль
function безопасноеДеление(числитель: float, знаменатель: float) -> Result<float, string> {
if знаменатель == 0.0 {
return Err("Нельзя делить на ноль")
}
return Ok(числитель / знаменатель)
}
// Пример использования
match безопасноеДеление(10.0, 0.0) {
case Ok(результат) => print("Результат деления: {результат}")
case Err(ошибка) => print("Ошибка: {ошибка}")
}2. Типобезопасность
// Обеспечение безопасности явным преобразованием — toInt возвращает Option<int>
let строковоеЧисло = "123"
let настоящееЧисло = match toInt(строковоеЧисло) {
case Some(значение) => значение
case None => {
print("Преобразование числа не удалось")
0
}
}
let результат = настоящееЧисло + 100
print("Результат безопасного вычисления: {результат}")Советы по оптимизации производительности
1. Оптимизация дорогих операций
// Используйте умножение вместо возведения в степень (для малых степеней)
let значение = 8
let квадрат = значение * значение // вместо значение ** 2
let куб = значение * значение * значение // вместо значение ** 3
// Используйте умножение вместо деления (float-домен)
let измерение = 8.0
let половина = измерение * 0.5 // вместо измерение / 2.02. Используйте короткое замыкание
// Размещайте дорогие вызовы функций позже
let результат = простоеУсловие() && дорогаяФункция()
// Оптимизируйте проверки на null
let значениеПоУмолчанию = "fallback"
let объект: Option<{ свойство: Option<{ подСвойство: string }> }> = None
let значение = объект?.свойство?.подСвойство ?? значениеПоУмолчаниюПонимание и правильное использование операторов Топазе позволяет вам писать эффективный и безопасный код! Всегда помните о приоритете операторов и типобезопасности.