Modules and packages
A Silk package is a named root with source files, public exports, and a manifest. Imports tell readers which package or local file supplies each symbol.
Create a package root
Keep implementation, examples, and tests in predictable folders.
mkdir -p logger/src logger/examples logger/tests
cd logger
[package]
name = "logger"
version = "0.1.0"
description = "A small Silk logging package."
[sources]
root = "src/lib.slk"
Export the package surface
The source namespace can be descriptive while downstream imports use the manifest package name.
package acme::logger;
import { println } from "std/io";
export enum Level {
Info,
Warn,
Error,
}
export fn write (level: Level, message: string) -> void {
match (level) {
Level::Info => {
println("[info] {s}", message);
},
Level::Warn => {
println("[warn] {s}", message);
},
Level::Error => {
println("[error] {s}", message);
},
}
}
Import from an example
Quoted imports are the everyday form for stdlib, local files, and package dependencies.
package logger_example;
import logger from "logger";
fn main () -> int {
logger::write(logger::Level::Info, "package import works");
return 0;
}
Check the module set
Compile commands load the files and packages needed for that build.
silk check src/lib.slk examples/main.slk
silk build examples/main.slk -o build/logger-example
Prefer quoted imports for application and package code. Direct paths such as
import acme::logger::write; are useful later for ABI-oriented definitions.
What changed
silk.tomlnamed the reusable package root.exportmarked the public surface.import logger from "logger";bound a downstream namespace.- The example proved the package boundary without exposing private files.
Chapter complete
Next, make absence and data shape choices visible in the type system.
Continue to types and optionals