1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
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'
```
|