| ↑ 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.