↑ Up |
To introduce private variables, one puts them into a
begin
-block. Only variables declared to be public
are visible outside of such a block.
begin public sind, cosd use math: pi, sin, cos deg = pi/180 function sind(x) return sin(x*deg) end function cosd(x) return cos(x*deg) end end print(sind(90))
Only sind
and cosd
are visible outside of begin ... end
.
The local variables deg
, pi
,
sin
, cos
are invisible.
It's actually a perfect black box. There is no way to determine
from outside, whether the local variables existed or not.
It is also possible to nest such begin
-blocks.
To understand the semantics, it should be said that public
is only a synonym for global
and begin ... end
is only a syntactic sugar for (fn|| ... end)()
.
Thus, the last example is identical to:
(fn|| global sind, cosd use math: pi, sin, cos deg = pi/180 function sind(x) return sin(x*deg) end function cosd(x) return cos(x*deg) end end)() print(sind(90))
Note that public
makes a variable completely public,
i.e. completely global. For intermediate visibility, a local
variable may be returned from a block:
sind = begin deg = pi/180 return |x| sin(x*deg) end
For more than one variable this looks a little bit clumsy:
{sind,cosd} = begin deg = pi/180 return { sind = |x| sin(x*deg), cosd = |x| cos(x*deg) } end
Two or more programs might use the same functionality.
In this case, if possible, this functionality should be moved into
a separate module which can be reused. As an example, let tools
be a module and let us put a function mean
(average, arithmetic mean) in it.
# File "tools.moss" # ================= function mean(a) return a.sum()/len(a) end # Main file "m.moss" # ================== use tools: mean a = [1,2,3,4] print(mean(a))
Sometimes, specific functionality is only needed irregularly. In certain cases it could be favourable to not load it until it is needed.
In Moss, loading modules is naturally dynamic. For example, we want to state a function that transforms a color name into its RGB value. Only if the name exceeds a certain range, the color will be taken from a larger table that is not loaded until needed.
# File "extended_colors.moss" # =========================== # This could be a very large table: extended_color_table = { "magenta": [0.5,0,0.2], "brown": [0.4,0.2,0] } print("(Extended colors loaded)") # Main file "m.moss" # ================== color_table = { "black": [0,0,0], "white": [1,1,1], "gray": [0.4,0.4,0.4], "red": [0.5,0.0,0], "green": [0,0.4,0], "blue": [0,0,0.8] } state = table{extended=false} ColorException = table{} function color(name) while true if name in color_table return color_table[name] else if state.extended raise table ColorException{ value = "Unknown color: "+name} else use extended_colors: extended_color_table color_table.update(extended_color_table) state.extended = true end end end end while true s = input("A color name please: ") try print(color(s),"\n") catch e if e: ColorException print(e.value,"\n") end end
Crucial is the line:
use extended_colors: extended_color_table
This line is executed at runtime, like an ordinary statement. In fact it is equivalent to:
extended_colors = load("extended_colors") extended_color_table = extended_colors.extended_color_table
Please take in mind that any module may be loaded dynamically, not only static data.