Результат: вы переведёте уже имеющиеся привычки в формы, принятые здесь, и узнаете, у каких привычек намеренно нет соответствия.
Что нужно знать: вы умеете читать код хотя бы на одном другом языке. Опыт работы с этим языком не предполагается.
Начните с того, что переносится без изменений
Многое на поверхности покажется знакомым. Роли значений, имён, функций, условий, циклов и коллекций легко узнать, а важные различия проверяющая система делает явными. Вы сможете в общих чертах объяснить пример ниже ещё до изучения всех деталей.
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 подошёл бы, если бы сорваться мог сам поиск, например если бы ему сначала пришлось прочитать файл. Выбор между отсутствием и ошибкой — то решение, которое язык просит принимать явно, и принятое один раз в сигнатуре, оно избавляет от догадок каждый вызывающий код.
Готовы двигаться дальше, если
Вы можете назвать четыре различия, сказать, у какой привычки из прежнего языка здесь нет соответствия, и выбрать между отсутствием и ошибкой для функции, которую собираетесь написать.
Если вы ещё не прошли курс, начните с раздела Первая программа, или сразу переходите к формам в разделе Краткий обзор синтаксиса.