Разделите программу на файлы и выберите имена, доступные из других файлов. Вы запустите учебный планировщик из двух файлов и разберёте ошибки доступа к приватным именам и циклического импорта.
Установите topaz по руководству Первая программа. Каждый файл .tpz является модулем. Отдельное объявление module не требуется.
Запустите программу из двух файлов
В рабочей папке, где ещё нет проекта study-plan, выполните следующие команды.
topaz init --root study-plan
cd study-planinit создаёт topaz.toml и src/main.tpz. Сохраните созданный манифест. Добавьте src/plan.tpz и замените src/main.tpz кодом ниже. После создания файла блокировки структура будет следующей.
study-plan/
├── topaz.toml
├── topaz.lock
└── src/
├── main.tpz
└── plan.tpzСохраните данные задач и функции в src/plan.tpz.
export record УчебнаяЗадача {
название: string,
минуты: int,
выполнена: bool = false,
}
function разобратьМинуты(текст: string) -> Result<int, string> {
match toInt(текст) {
case Some(значение) if значение > 0 => Ok(значение)
case _ => Err("minutes must be a positive integer")
}
}
export function создатьЗадачу(
название: string,
текстМинут: string,
выполнена: bool = false,
) -> Result<УчебнаяЗадача, string> {
let минуты = разобратьМинуты(текстМинут)?
Ok(УчебнаяЗадача { название: название, минуты: минуты, выполнена: выполнена })
}
export function подвестиИтог(задачи: Array<УчебнаяЗадача>) -> string {
let mut осталось = 0
for задача in задачи {
if !задача.выполнена {
осталось = осталось + задача.минуты
}
}
"tasks={задачи.length}, remaining={осталось} minutes"
}В src/main.tpz импортируйте три имени, используемые приложением.
import src.plan { УчебнаяЗадача, создатьЗадачу, подвестиИтог }
export function main(аргументы: Array<string>, ввод: string) -> Result<int, string> {
let задачи: Array<УчебнаяЗадача> = [
создатьЗадачу("Run first program", "10", true)?,
создатьЗадачу("Build application", "25", false)?,
]
print(подвестиИтог(задачи))
Ok(0)
}Выполните команды внутри study-plan, рядом с topaz.toml.
topaz lock --root .
topaz check --root . --locked
topaz run --root . --lockedКоманда lock создаёт topaz.lock. Проверка завершается с кодом 0, а программа печатает итог.
tasks=2, remaining=25 minutesПуть src.plan указывает на src/plan.tpz внутри выбранного корня. Компилятор проверяет входной файл и импортируемые модули, следуя и по их импортам. Эти файлы образуют единицу компиляции. Файлы, не связанные с этой точкой входа, не проверяются.
Выберите имена для экспорта
Объявление по умолчанию приватно. Добавьте export, чтобы использовать его из другого модуля. Здесь экспортированы УчебнаяЗадача, создатьЗадачу и подвестиИтог. Функция разобратьМинуты остаётся приватной.
Если src/main.tpz попытается импортировать или вызвать разобратьМинуты, проверка завершится ошибкой. Вызывайте экспортированную создатьЗадачу. Если вспомогательную функцию нужно открыть, добавьте export к её объявлению в src/plan.tpz. Импортированные привязки доступны для чтения без возможности изменения.
| Задача | Форма импорта |
|---|---|
| Выбрать имена | import src.plan { УчебнаяЗадача, создатьЗадачу } |
| Задать псевдоним выбранного имени | import src.plan { подвестиИтог as показатьИтог } |
| Сгруппировать имена под префиксом | import src.plan as план |
Последняя форма создаёт пространство имён, то есть префикс для поиска экспортированных имён при компиляции. Через него можно вызвать план.создатьЗадачу(...). Само пространство имён не является значением во время выполнения.
В аннотации типа можно написать план.УчебнаяЗадача. Чтобы создать УчебнаяЗадача { ... }, импортируйте УчебнаяЗадача напрямую. Форма план.УчебнаяЗадача { ... } отклоняется. Если вы написали import src.plan as план { подвестиИтог }, замените её одной из отдельных форм импорта выше.
Найдите файлы от правильного корня
Сопоставьте путь с точками с точными именами файлов и папок под корнем. Располагайте импорты в начале файла, перед остальными элементами.
Команды пакета читают точку входа, зависимости и цель сборки из topaz.toml. При явном указании файла его папка становится корнем по умолчанию. Параметр --root позволяет выбрать содержащую его папку. Если src.plan не найден, проверьте --root и расположение src/plan.tpz.
Зависимости инициализируются один раз, до импортирующего их модуля. Импортируемый модуль может содержать объявления и привязки. Свободные циклы и присваивания верхнего уровня отклоняются. Перенесите такую работу в функцию и вызовите её из точки входа.
Разорвите цикл импортов
В отдельной папке сохраните этот код как a.tpz.
import b
export function изА() -> int {
1
}Рядом сохраните следующий код как b.tpz.
import a
export function изБ() -> int {
2
}В этой папке команда topaz check a.tpz --root . завершается с ненулевым кодом и сообщает о цикле.
error[TPZ3006]: import cycle: a -> b -> a
--> a.tpz:1:8
|
1 | import b
| ^
a.tpz: 1 diagnosticПеренесите общие объявления из a.tpz и b.tpz в третий модуль и импортируйте его из обоих файлов. Другой вариант состоит в удалении зависимости в одном направлении. В проверке циклов участвует каждый импорт, включая импорты для типов.
Формы, которые компилятор отклоняет
Компилятор отклоняет use, строковые и шаблонные пути, псевдоним вместе со списком выбора и импорт ради побочного эффекта. Также отклоняются списки экспорта, групповой и повторный экспорт, переименование при экспорте и export let mut. Путь импорта не может выходить за корень, а пространство имён не открывает приватные имена.
Продолжите с Первым приложением, чтобы добавить тесты и собрать эту программу. Зависимости и блокировка описаны в разделе Пакеты и распространение. Для сравнения знакомого синтаксиса с поддерживаемыми формами используйте Запрещённые и отложенные формы.