Topazdocs
Встроенный справочник

Основные функции

Каноническая поверхность public-примеров Topaz для небольшого набора built-in функций и helper-имён, заданного SPEC.

Topaz намеренно держит public canonical поверхность функций небольшой. Имена ниже можно использовать в public-примерах без изобретения большой стандартной библиотеки. Будущая спецификация стандартной библиотеки может уточнить эту поверхность, но canonical-документация остаётся в рамках форм ниже.

Вывод и преобразование

print принимает только string. Нестроковые значения выводятся через интерполяцию. toInt(text: string) возвращает Option<int> и никогда не падает молча: обрабатывайте случай None явно.

TOPAZ
print("Hello, Topaz!")

// toInt возвращает Option<int>
let ответ = match toInt("42") {
    case Some(значение) => значение
    case None => 0
}
print("Разобранный ответ: {ответ}")
TOPAZ
function разобратьПорт(текст: string) -> Result<int, string> {
    if текст == "" {
        return Err("Порт обязателен")
    }

    match toInt(текст) {
        case Some(порт) => Ok(порт)
        case None => Err("Порт должен быть целым числом")
    }
}

Строки

Строки не индексируются и не предоставляют .length. Доступ на уровне скаляров идёт через s.scalars(), возвращающий Array<string> из односкалярных строк.

TOPAZ
let слово = "topaz"
let скаляры = слово.scalars()           // ["t", "o", "p", "a", "z"]
let длина = слово.scalars().length      // 5
print("Число скаляров: {длина}")

Файлы и ресурсы

Операции с ресурсами являются Result-first. Откройте ресурс через ?, зарегистрируйте очистку через defer и верните результат последней операции.

TOPAZ
function прочитатьТекст(путь: string) -> Result<string, string> {
    let файл = open(путь)?
    defer { файл.close() }

    let содержимое = файл.read()?
    Ok(содержимое)
}

function записатьТекст(путь: string, содержимое: string) -> Result<(), string> {
    let файл = open(путь)?
    defer { файл.close() }

    файл.write(содержимое)
}

JSON и Regex (зарезервированные имена)

JSON.parse и regex.matchзарезервированные имена стандартной библиотеки: они не входят в типизированный минимум, пока не специфицированы JSONValue, Regex и Match. Канонические примеры могут упоминать их только там, где форма возвращаемого значения не важна, с примечанием об отложенности. Не пишите код, зависящий от того, что они возвращают.

Regex значения-шаблоны каноничны уже сегодня через однострочную tagged-форму r"...":

TOPAZ
let цифры = r"^[0-9]+$"     // значение regex-шаблона (API сопоставления пока нет)

Коллекции

Канонические конструкторы коллекций — Array.of, Map.new и Set.of. Изменяющие операции с коллекциями требуют mutable binding.

TOPAZ
let mut числа = Array.of(1, 2, 3)
числа.push(4)

let количество = числа.length
let третий = числа[2]           // 3 — прямая индексация даёт фолт вне границ
let безопасно = числа.get(10)   // None — чтение без фолта, возвращает Option<int>
let естьЧетыре = 4 in числа

print("Количество: {количество}")
print("Третий: {третий}")
print("Есть четыре: {естьЧетыре}")

arr.get — каноническое чтение без фолта; предпочитайте его всякий раз, когда индекс может выйти за границы.

TOPAZ
let mut оценки: Map<string, int> = Map.new()
оценки.insert("alice", 10)
оценки.insert("bob", 20)

let оценкаAlice = оценки.get("alice")    // Some(10) — None, если ключа нет
let удалено = оценки.remove("bob")       // Some(20) — Some(старое) если был, иначе None
let знаетAlice = "alice" in оценки.keys  // принадлежность идёт через представление keys
print("Есть alice: {знаетAlice}")

m.keys — это снимок Array<K> в порядке вставки ключей: последующее изменение карты не меняет уже созданный массив ключей. Прямое x in map не канонично; используйте x in map.keys.

TOPAZ
let mut теги = Set.of("docs")
теги.add("v5")

let естьDocs = "docs" in теги
let убрано = теги.remove("docs")         // true, только если элемент был удалён
print("Есть docs: {естьDocs}")

map, filter и reduce

map, filter и reduce — ordinary functions. Их сигнатуры — map(xs, f), filter(xs, f) и reduce(xs, initial, f): начальное значение идёт перед редьюсером. В pipelines передавайте piped value через _.

TOPAZ
let числа = Array.of(1, 2, 3, 4, 5, 6)

let результат = числа
    |> filter(_, x => x % 2 == 0)
    |> map(_, x => x * x)
    |> reduce(_, 0, (накоплено, x) => накоплено + x)

print("Сумма квадратов чётных: {результат}")

Result helper-имена

Для восстанавливаемых ошибок используйте Ok, Err, match и распространение ?.

TOPAZ
function загрузитьПорт(путь: string) -> Result<int, string> {
    let содержимое = прочитатьТекст(путь)?
    разобратьПорт(содержимое)
}

match загрузитьПорт("app.port") {
    case Ok(порт) => print("Порт: {порт}")
    case Err(ошибка) => print("Ошибка конфигурации: {ошибка}")
}

Concurrent-блоки

concurrent возвращает запись результатов arm. В canonical public-примерах блок else должен возвращать fallback-запись той же shape.

TOPAZ
function снимокПрофиля() -> { имя: string } {
    { имя: "Topaz" }
}

function недавняяАктивность() -> Array<string> {
    Array.of("login", "edit")
}

function пустойПрофиль() -> { имя: string } {
    { имя: "offline" }
}

let панель = concurrent(timeout: 3s) {
    профиль: снимокПрофиля()
    активность: недавняяАктивность()
} else {
    {
        профиль: пустойПрофиль(),
        активность: Array.of("offline")
    }
}

print("Элементов активности: {панель.активность.length}")

Tagged Templates

Tagged templates являются значениями. Shell template tag создаёт shell template value; он сам по себе не выполняет команду.

TOPAZ
let имяПриложения = "topaz"
let idПользователя = 42
let директория = p"/var/{имяПриложения}"

let путьКонфига = p"/etc/{имяПриложения}/config.toml"
let цифры = r"^[0-9]+$"
let командаСписка = sh"ls {директория}"
let запрос = sql"select * from users where id = {idПользователя}"

Эта страница намеренно узкая: если helper не перечислен здесь и не определён рядом с примером, не считайте его canonical Topaz public surface.