Skip to content

Modules and Imports

A file’s module name is its filename without .gray. There are no module declarations. Standard library modules are imported with @, local files with a relative path.

main.gray
import "./helpers"
do main() {
println(helpers.greet("Grayscale"))
}
helpers.gray
do greet(name string) -> string {
return "Hello, ${name}!"
}

Relative paths resolve from the directory of the importing file, not from the entry point.

Importing a directory merges every .gray file directly inside it into one module named after the directory. Subdirectories are separate modules.

main.gray
import "./models"
do main() {
mut user = models.User{name: "alice"}
println(models.describe(user))
}
models/user.gray
const User struct {
name string
}
models/describe.gray
do describe(user User) -> string {
return "user ${user.name}"
}

Separate imports with commas. Only local imports can be aliased, which is how you resolve a name collision or import a file whose name is not a valid identifier.

main.gray
import @math, greeter "./my-greeter"
do main() {
println(greeter.hello())
println(math.sqrt(16.0))
}
my-greeter.gray
do hello() -> string {
return "hello"
}

Everything at the top level of a file is public by default. private keeps a declaration inside its own file: it works on functions, constants, structs, enums and aliases, not only struct functions.

main.gray
import "./mathlib"
do main() {
println(mathlib.factorial(5))
}
mathlib.gray
private const LIMIT i64 = 20
private do valid(n i64) -> bool {
return n >= 0 && n <= LIMIT
}
do factorial(n i64) -> i64 {
if !valid(n) {
return 1
}
mut result i64 = 1
for i in range(2, n + 1) {
result = result * i
}
return result
}

Code in main.gray can call mathlib.factorial but not mathlib.valid or mathlib.LIMIT. Struct functions can be private as well; see the Structs page.

using lets you call a module’s functions without the prefix. Put it at file scope or inside one function.

import @strings
using strings
do main() {
println(to_upper("hello"))
}

import and use @strings does both in one line. If two modules in scope both define a name, call it with its prefix.

import and use @math
do main() {
println(sqrt(25.0))
}