Изучение Топаза

Переход с других языков

Сопоставьте то, что вы уже знаете из Python, JavaScript, Java или Rust, с формами этого языка, включая намеренно отсутствующие части.

Результат: вы переведёте уже имеющиеся привычки в формы, принятые здесь, и узнаете, у каких привычек намеренно нет соответствия.

Что нужно знать: вы умеете читать код хотя бы на одном другом языке. Опыт работы с этим языком не предполагается.

Начните с того, что переносится без изменений

Многое на поверхности покажется знакомым. Роли значений, имён, функций, условий, циклов и коллекций легко узнать, а важные различия проверяющая система делает явными. Вы сможете в общих чертах объяснить пример ниже ещё до изучения всех деталей.

TOPAZ
record Task {
    title: string,
    minutes: int
}

function totalMinutes(tasks: Array<Task>) -> int {
    let mut total = 0
    for task in tasks {
        total = total + task.minutes
    }
    total
}

Если вы писали на Python, JavaScript, Java или Rust, вы уже можете сказать, что здесь происходит. Ради этого мы отсюда и начинаем. Различий, достойных вашего внимания, немного, и они собраны ниже.

Четыре различия, которые действительно важны

Изменяемость включается явно. Имя, объявленное обычным let, переприсвоить нельзя. Запись let mut заявляет, что переприсваивание входит в замысел. В языках, где переприсваивание легко доступно, нередко приходится читать больше тела функции, чтобы понять, какие имена меняются. Здесь ответ есть в объявлении.

Восстанавливаемая ошибка — это значение. Здесь нет исключений, которые нужно ловить. Функция с восстанавливаемой ошибкой возвращает Result, а вызывающий код либо обрабатывает её, либо передаёт выше через ?. Поэтому форма ошибки видна на границе вызова, а не выводится из тела или соглашений об исключениях. Ошибки времени выполнения остаются отдельной невосстанавливаемой границей.

Отсутствие записано в типе. Обычный необязательный результат использует Option<T>. Внешние nullable-данные могут использовать T | null, и эти две модели остаются раздельными. В обоих случаях проверяющая система требует обработать отсутствие до обращения со значением как с присутствующим.

У полномочий хоста есть явная граница. Файловые операции и ввод-вывод доступны только через выбранный профиль хоста или продукта, а веб-продукт получает лишь объявленные ограниченные возможности. Сигнатура функции показывает данные и восстанавливаемые ошибки; импорты, конфигурация пакета и выбранный профиль дополняют картину полномочий. В разделе Чтение реального файла используются все эти признаки.

Чего здесь нет намеренно

О привычках, у которых здесь нет соответствия, лучше узнать пораньше, чтобы перестать за них хвататься.

Здесь нет иерархии классов и наследования. Формы задаются записями, а поведение живёт в функциях, которые их принимают. Если чутьё подсказывает вам моделировать базовым классом и переопределениями, моделируйте записями и явными функциями.

Здесь нет рефлексии над программой во время выполнения, нет динамической диспетчеризации через таблицу протокола и нет полиморфизма строк. Точный список отложенного приведён в разделе Записи и номинальные данные.

Здесь нет неявного преобразования между видами чисел. int не превращается в float оттого, что так было бы удобнее окружающему выражению.

Эти границы заданы намеренно. Важные решения остаются видимыми в объявлениях и конфигурации продукта, но одна сигнатура функции не выдаётся за полное описание всех взаимодействий с хостом.

Таблица перевода на первый час

Ваш dict, Map или HashMap соответствует коллекции, о которой рассказывает раздел Коллекции и включения. Класс, содержащий только данные, часто соответствует записи. Границу, похожую на интерфейс, начинайте с явных сигнатур функций; для поддерживаемого обобщённого контракта используйте статический протокол без динамической диспетчеризации во время выполнения. Восстанавливаемая логика try/except соответствует возвращаемому Result. Обычный необязательный результат использует Option, а внешние nullable-данные при необходимости — T | null; проверяющая система сохраняет различие явным.

Попробуйте

Вам нужна функция, которая ищет задачу по названию и может её не найти. Прежде чем открыть ответ, решите, каким должен быть тип её результата.

Показать ответ

Option с задачей, а не задача. Ничего не найти — обычный исход поиска, а не ошибка, поэтому он попадает в тип как отсутствие. Result подошёл бы, если бы сорваться мог сам поиск, например если бы ему сначала пришлось прочитать файл. Выбор между отсутствием и ошибкой — то решение, которое язык просит принимать явно, и принятое один раз в сигнатуре, оно избавляет от догадок каждый вызывающий код.

Готовы двигаться дальше, если

Вы можете назвать четыре различия, сказать, у какой привычки из прежнего языка здесь нет соответствия, и выбрать между отсутствием и ошибкой для функции, которую собираетесь написать.

Если вы ещё не прошли курс, начните с раздела Первая программа, или сразу переходите к формам в разделе Краткий обзор синтаксиса.