All docsModules

Modules

The use statement: a one time, compile time splice of another file's declarations into yours.

There is no import system in Venutian, in the sense of a runtime step that loads a module object, caches it, and lets you qualify into its namespace. There is exactly one rule: use "relative/path.ven" splices that file's make, tool make and shape declarations into the file that uses it, once, at compile time. Everything else about "modules" in Venutian follows from that one rule.

The path is relative to the file, not the project

A use "path.ven" resolves path.ven relative to the directory of the file containing that use statement, and nothing else is ever consulted: no search path, no environment variable, no standard library directory to check first, because Venutian's core builtins are always available with no use at all. You can organize files into subdirectories exactly the way you would expect:

venutian
:: pkgtest/main.ven
use "utils/mathy.ven"
print double(21)
venutian
:: pkgtest/utils/mathy.ven
make double(n)
    give n * 2
shell
venutian run pkgtest/main.ven
output
42

Only declarations arrive, and they arrive unqualified

use copies make, tool make and shape declarations into the importing file's namespace directly, with no module.function() qualification of any kind: a name arrives exactly as if you had typed its declaration yourself. The top level statements of a file brought in with use, anything that is not a declaration, never run, not on the first use and not on any later one:

venutian
:: lib_with_print.ven
print "this should never print if use only splices declarations"
make greet(name)
    give "hello " + name
venutian
:: importer_print_test.ven
use "lib_with_print.ven"
print greet("Venutia")
shell
venutian run importer_print_test.ven
output
hello Venutia

Only hello Venutia prints. The print statement sitting at the top of lib_with_print.ven is silently dropped, with no diagnostic telling you it happened. If you keep test code at the top level of a file you expect to use elsewhere, that code will not run once something else uses the file.

What Venutian does not have

There is no package directory convention, no __init__-style initialization file, no dotted module path, and no relative import syntax with leading dots: use takes one Text literal path, resolved once, as an ordinary filesystem path. There is no module cache to reuse across a second use of the same file, because the file's code was never run in the first place, only its declarations spliced in, so there is nothing to reload and no import ... as aliasing syntax, since a name brought in with use always arrives under its own declared name.

Because there is no namespace boundary between files, two files brought in with use cannot both declare a function with the same name: a collision is an ordinary duplicate declaration error, the same as declaring the same name twice in one file. A use cycle, two files that use each other, resolves without error, because use never executes anything that could be left half initialized: it only ever splices declarations.

A file's own top level code only runs when you name it directly

A .ven file's top level statements run only when that file is the one passed to venutian run, never when another file uses it. There is no if this is the main file idiom to write, because the question is already answered by which file you ran.

See getting started for venutian run, and types and shapes for what a shape declaration looks like once it is brought into another file with use.