OxL Справочник OxL
РусскийEnglish

Шаг 9. Модули и пакеты

Зачем#

Один файл — хорошо для эксперимента, но программа растёт. OxL делит код на пакеты (единица сборки и версионирования) и модули (единица видимости). Граница модуля — это граница инкапсуляции: то, что не объявлено pub, снаружи не видно, и изменение внутренностей модуля не ломает чужой код.

  • Пакет — каталог с файлом oxl.toml.
  • Модуль — каталог внутри src/; все .oxl файлы одного каталога образуют один модуль и разделяют имена.
  • Порядок объявлений в модуле не важен; циклические зависимости между модулями — ошибка.

Создаём проект#

sh
oxl new geo && cd geo

Получится пакет такого вида; добавьте в него модуль shapes и тест:

oxl
geo/
├── oxl.toml
├── src/
│   ├── main.oxl            # корневой модуль, здесь fn main
│   └── shapes/
│       └── shapes.oxl      # модуль shapes
└── tests/
    └── shapes_test.oxl

oxl.toml — манифест пакета (III.2):

toml
[package]
name = "geo"
version = "0.1.0"
edition = "2027"

src/shapes/shapes.oxl:

oxl
pub(api) data Circle { pub(api) r: f64 }

pub(api) fn area(c: &Circle) -> f64 pure => 3.0 * c.r * c.r

fn secret() -> i32 pure => 42

src/main.oxl:

oxl
use self.shapes { Circle, area }

fn main() io {
  let c = Circle{ r: 2.0 }
  print("area {area(&c)}")
}

tests/shapes_test.oxl (тесты видят пакет через super):

oxl
use super.shapes { Circle, area }

test "area of unit circle" {
  assert_eq(area(&Circle{ r: 1.0 }), 3.0)
}
sh
$ oxl run
area 12.0
$ oxl test
test geo.tests::area of unit circle ... ok

(Этот проект проверяется при подготовке документации: oxl run и oxl test дают приведённый вывод.)

Разбор#

  • use self.shapes { Circle, area } — импорт из модуля своего пакета. Первый сегмент пути — std (стандартная библиотека), self (этот пакет), super (родительский модуль, используется в тестах) или имя зависимости из oxl.toml.
  • Видимость: без модификатора — внутри модуля; pub — внутри пакета; pub(api) — всем, кто зависит от пакета (это публичный API: oxl publish проверяет совместимость по SemVer, §2.3). Поэтому fn secret() снаружи недоступна.
  • Поля data имеют собственную видимость: без pub(api) у поля r литерал Circle{ r: 2.0 } вне модуля не скомпилируется (visibility).
  • Прелюдия std.core (List, Map, print, sleep, …) импортируется автоматически; остальное — use std.io { File }.
  • Неиспользованный импорт — предупреждение; конфликт имён двух импортов — ошибка, если имя используется.

Команды проекта: oxl run -- аргументы, oxl test, oxl fmt, oxl check; зависимости добавляются в [dependencies] манифеста, а oxl.lock фиксирует версии.

Типичная ошибка: неверный импорт#

oxl✓ проверяется в CI
use std.nothing { Thing }

fn main() io {
  print("hi")
}
error
unresolved-import

unresolved-import: в std нет такого модуля. Список модулей — в справочнике стандартной библиотеки; для своих модулей проверьте, что каталог лежит в src/ и что первый сегмент пути — self.

Что запомнить#

  • Пакет = oxl.toml; модуль = каталог; pub — в пакете, pub(api) — наружу.
  • Пути: std…, self…, super…, имя зависимости.
  • Тесты лежат в tests/ или рядом с кодом.

Дальше: тесты.

См. также

OxL 1.0.0-beta · Версия документации 1.0.0-beta© OxwaldLink · сгенерировано из Стандарта, исходников std и руководства