3.6. modules and loading
To reuse code across projects, alv
code can be split up over multiple files
and loaded as modules.
loading modules
To load modules, require
, import
and import*
can be used:
require
loads a module and returns its value.import
requires a module and makes its value available in a symbol with the same name.(import my-module)
is equivalent to(def my-module (require "my-module"))
.import*
loads a module and merges all exported symbols into the active scope.(import* my-module)
is equivalent to(use (require "my-module"))
. It assumes the module exports a scope with definitions to be imported.
require
can load two types of modules: native modules written in
Lua/MoonScript (such as everything listed in this reference), and modules
written in alv
itself. The latter are looked up relative to the file
containing the (require …)
expression, and are should match the module name
with the file extension .alv
; i.e. my-module.alv
for the example above.
If a module is imported multiple times, it is only evaluated once and its result is reused.
writing modules
When an alv script file is imported, its ‘value’ is that of the last expression inside it:
my-module.alv
(print "loading my-module...")
4
main.alv
(import* string)
(print (str "my-module's value is " (require "my-module")))
loading my-module...
my-module's value is 4
Often it is useful to export multiple values from a file, for example when
writing a library containing multiple functions. There are two operators to
allow this: export
and export*
.
export
creates a new scope and evaluates all its arguments in it, just
like do
. However it doesn’t return the result of the evaluations, but
rather the newly created scope. It can therefore be combined with def
,
defn
etc. to export symbol definitions:
my-module.alv
(import* math string)
(export
(def a-value 7)
(defn print-doubled (x) (print (str x " doubled is " (* x 2)))))
main.alv
(import* string)
(import my-module)
(print (str "my-module/a-value is " my-module/a-value))
(my-module/print-doubled 4)
my-module/a-value is 7
4 doubled is 8
export*
on the other hand operates on the containing scope rather than
creating a new one. When Used without any arguments, it returns the containing
scope itself and can be used to (re-)export everything that is currently
defined. When arguments are passed, only those symbols that are explicitly
mentioned are exported:
my-module.alv
(def a 1)
(def b 2)
(def c 3)
(export* a b)
main.alv
(import* string)
(import* my-module)
(print (str "a is " a))
(print (str "b is " b))
(print (str "c is " c))
a is 1
b is 2
reference error: undefined symbol 'c'