6. Modules
A program grows past one file by splitting into modules. Each .kor file is
a module; import runs another one and gives you an object to reach into.
Importing a file
Say geometry.kor sits next to your program:
pi = 3.14159
fn area(r):
return pi * r * r
Import it by relative path — ./ for "next to me", ../ to go up:
import "./geometry"
print(geometry.area(2))
import "./geometry" binds geometry (the file's name, no extension; the .kor
is implied). Reach members with ., like a class instance — this prints
12.56636.
To pick a different name — or avoid a clash — add as:
import "./geometry" as geo
print(geo.area(1))
(These blocks aren't executed by the CI check the way the rest of the guide is — they need real files on disk. The behaviour is covered by the interpreter's own module tests.)
What's public
Every top-level name in a module is visible through the module object, except
names starting with _:
fn shout(s):
return _emphasise(s.upper())
fn _emphasise(s):
return s + "!!!"
From another file, util.shout("go") returns "GO!!!", but reaching
util._emphasise is an error. Inside util.kor, _-names work normally — the
line is only drawn at the module boundary.
Loaded once
A module runs the first time it is imported. Import it again — from the same file
or a different one — and you get the same object back, already initialised, so
geometry == also_geometry is true.
Two modules that import each other are an error (E0315): Korrin will not
hand you a half-loaded module. If two modules need something in common, put it in
a third module they both import.
The standard library
A specifier with no ./ is a built-in module — part of Korrin, imported the
same way, and it works from any program:
import "math"
print(math.sqrt(144))
print(math.floor(3.7))
print(math.max(2, 9, 5))
# => 12.0
# => 3
# => 9
math has sqrt, pow, floor, ceil, round, abs, min, max, and the
constants pi and e.
io talks to the outside world — files and command-line arguments:
import "io"
io.write_file("note.txt", "hello from Korrin\n")
print(io.read_file("note.txt").trim())
print(io.args())
An io call that fails raises (E0316), so wrap it in try when the file
might not be there:
import "io"
try:
config = io.read_file("config.txt")
except e:
config = "(defaults)"
Full list of both modules in specification §11.
Because "math" always means the built-in, a file called math.kor next to your
program does not shadow it — import that one as "./math".