Modules and Packages
Every Polar file is a module. Modules are grouped into projects, which you run, and packages, which other projects depend on.
Importing with uses
The uses zone lists the modules a file needs. There are
three forms:
uses
Std.List
Money as M
Std.Prelude { show }
-
Std.Listimports the module under its last name, so you writeList.map. -
Money as Mpicks a different name, so you writeM.add. -
Std.Prelude { show }also brings trait methods into scope, so you can callshow(x)without a prefix.
Where modules come from
-
Paths starting with
Std.come from the standard library. - Paths starting with a dependency's module name come from that package.
-
Everything else comes from your project's
src.uses Moneyloadssrc/money.px, which declaresmodule Money.
Exports
The exports zone lists the functions, constants,
effects and hosts that other modules can use. Anything not listed
stays private to the file.
Types are different: they're always exported, so they never go in the list. If you add one anyway, Polar tells you to remove it:
error[POLAR0301]: `Shape` is a type, and types are always exported
--> tour.px:115:3
|
115 | Shape
| ^^^^^
|
= help: remove it from `exports`
Packages
A package is a library: it's checked and depended on, but not run by
itself. Its polar.toml has a
[package] section instead of [project],
and claims one top-level module name:
[package]
name = "simple_framework"
module = "Framework" # claims every `uses Framework.…`
Inside the package, file names leave out the claimed name:
src/html.px is module Html, and everyone
imports it as Framework.Html, including the package's
own files.
Dependencies
Projects and packages list their dependencies by path:
[dependencies]
simple_framework = { path = "../simple_framework" }
Paths are relative to the polar.toml. Dependencies
compile into dist/_deps/<package>/, so the build
stays self-contained.
Launchers
Some programs need more than main to start. A web app
built for Browser and Node needs a server
that hands out the browser bundle, answers
bridge calls and runs routes. A package
can provide that as a launcher, a Node script:
# in the package
[launcher]
script = "launcher/serve.mjs"
A project picks a launcher from one of its direct dependencies, and can pass it options:
# in the project
[run]
launcher = "simple_framework"
options = { port = 3000 }
Now polar run builds every host and hands the result to
the launcher. The launcher receives a manifest file describing the
build:
{ "version": 1, "project": "web_posts", "root": "/abs/projects/web_posts",
"out": "/tmp/polar-run-…/dist", "main": "main.js",
"hosts": { "Browser": "/tmp/…/dist/Browser", "Node": "/tmp/…/dist/Node" },
"options": { "port": 3000 } }
polar build bundles the launcher too, so
polar start or node dist/start.mjs runs
the built app without compiling again.
Note: The launcher script is copied on its own, so it can't import files that sit next to it.
Packages can also add new zones to the language. That's the last guide: Zone Plugins.