Skip to content
Kavachकवच

Modules: use

● Intermediate2 min

use brings in a module, the standard library or a dependency; use a.b.{X, y} brings names in directly.

use billing.invoice                    // then write invoice.create(…)
use billing.invoice.{Invoice, create}  // then write create(…)
use std.json                           // the standard library
use std.time.{Date, utc}               // a std type and function
use std.collections.Set as HashSet     // a new name
syntax: Kavach code
  • Names are looked up in your own modules first, then std, then dependencies.
  • Some names need no use at all: the built-in types, print, debug, ask, panic, env, Shared and Channel.
  • A dependency is used by its name the same way: see Packages.
  • use std.time.{Date, utc} names a standard module's types and functions that are written in Kavach. A function the runtime provides can't be named alone, and the message says what to write:
use std.fs.{read_text}

fn main() uses Fs {
    print(read_text("notes.txt") catch "")
}

The compiler refused the program:

kavach run std-runtime-name.kav

error: `read_text` can't be named alone: write `use std.fs` and `fs.read_text` (spec 14.1)
std-runtime-name.kav: Kavach code, then what running it prints
tested

A type through its module

Without bringing a type in by name, write it through its module, as you write its functions: regex.Regex, regex.RegexError, fs.FsError. That works for parameters, results and errors:

use std.regex

fn first_number(r: regex.Regex, text: String) -> String? {
    if let c = r.captures(text) {
        return c[1]
    }
    none
}

fn order_pattern() -> regex.Regex ! regex.RegexError {
    try regex.new(r"order (\d+)")
}

fn main() uses Console {
    const r = order_pattern() catch e => panic("{e}")
    print(first_number(r, "order 4471 shipped") ?? "none")
    print(first_number(r, "no number here") ?? "none")
}

The program ran and printed:

kavach run std-type-path.kav

4471none
std-type-path.kav: Kavach code, then what running it prints
tested

Re-exports

pub use makes the names it brings in part of the module too. So a package can declare each public type in a file of its own and show them all from its root:

use shop

fn describe(o: shop.Order) -> String {
    "{o.qty} x {o.item}"
}

fn main() {
    print(describe(shop.place("pen", 3)))
}

The program ran and printed:

kavach run

3 x pen
src/main.kav: Kavach code, then what running it prints
  • A re-exported name is the same declaration, not a copy: shop.Order and shop.orders.Order are one type.
  • Each name must be pub where it is declared, and a re-exported name can be re-exported again.
  • Only names are re-exported, not a whole module:
pub use std.math

fn main() {
    print(math.sqrt(4.0))
}

The compiler refused the program:

kavach run re-export-module.kav

error: `pub use` re-exports names, not a whole module: write `pub use module.{Name, …}` (spec 10.2)
re-export-module.kav: Kavach code, then what running it prints