Language

Modules and imports

Each .vary file is a module and directories are packages. You use imports to pull in functions, classes, and other definitions. The compiler resolves the full dependency graph at compile time.

The prelude

A small set of types and functions is available in every file without imports. Everything else requires an explicit import statement.

Prelude types (always available):

CategoryTypes
PrimitivesInt, Float, Bool, Str, None
CollectionsList, Dict, Set
ResultsResult, Ok, Err
SpecialNever

Prelude functions (always available): print, input, len, str, int, float, bool, range, abs, min, max, sorted, map, filter, reduce, any, all, sum, and others.

Non-prelude types require imports. If you use Json, Path, Clock, Rng, Decimal, or any other stdlib type, you must import the owning module. The compiler tells you which module to import:

error: Type 'Json' requires 'import json'

Common imports:

TypeRequired import
Json, JsonValue, JsonErrorimport json
Decoder, DecodeErrorimport json
Pathimport path
ReadPath, WritePath, DirPathimport fs
Clock, Duration, Date, Instantimport time
Rngimport random
TemplateEngine, TemplateErrorimport template
HttpResponse, HttpErrorimport http
Decimalimport decimal
Moneyimport money
Urlimport url
CryptoHashimport crypto
Command, ProcessResultimport process

This makes dependencies visible: you can tell which modules a file uses by reading its import block.

Imports

import math_utils
import math_utils as m
from math_utils import square, cube
from math_utils import square as sq

Modules are files. A file math_utils.vary defines module math_utils.

Access control

Names starting with _ are private and not exported:

def public_func() -> Int {
    return _helper()
}

def _helper() -> Int {
    return 42
}

Controlling exports

By default, all non-underscore names are exported. Use __all__ to restrict:

let __all__ = ["public_func", "CONSTANT"]

def public_func() -> Int {
    return 42
}

def internal_func() -> Int {
    return 0
}

let CONSTANT: Int = 100

Only public_func and CONSTANT are importable from this module.

Relative imports

Use dots to import relative to the current file's directory:

from .sibling import helper          # same directory
from ..parent_module import Config   # parent directory
from .subpkg.util import format      # subdirectory

One dot (.) means the current directory, two dots (..) means the parent, and so on. Relative imports only resolve within the project - they cannot escape the module root.

Module root discovery

The compiler finds the module root by walking up from the entry file until it finds a vary.toml file or the filesystem root. All absolute imports (e.g., import utils) resolve relative to this root. If no vary.toml exists, the entry file's directory is the root.

← Error handling
Concurrency →