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")))

```output
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)

```output
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))

```output
a is 1
b is 2
reference error: undefined symbol 'c'
```
