Let Expressions and Blocks - Spicery/Nutmeg GitHub Wiki
The let-syntax is used to neatly encapsulate intermediate variables, so they are only visible in the parts of the program that need to see them. It has two versions:
- let-expression:
let DECLARATIONS in EXPRESSIONS (endlet|end)
- let-declaration:
let DECLARATIONS (endlet|end)
Let Expressions
The let-expression is the commonest form of let-syntax. It is used to define some intermediate variables that are then used inside an expression. For example:
let d := sqrt( x**2, y**2 )
in
x/d + y/d
end
Let Declarations
As an alternative the in
part can be a sequence of bindings rather than a sequence of expressions:
let
x2 = x**2
y2 = y**2
d := sqrt( x2, y2 )
in
sin := x/d
cos := y/d
end
Modifiers
In a let-expression, the declarations can be annotated by the modifiers private
, public
or common
with the following rules:
Note that,
block/endblock
Like a let
expression, the block/endblock
form is used to define some variables whilst hiding some auxiliary variables. The difference is that the hidden and exposed variables can be freely interleaved because they are marked as private
or public
:
- Any variable declared as
private
is entirely local to that scope, as you might expect. This is the default modifier, so these are usually omitted in this context. - Variables declared as
public
are visible outside that scope, as if they were declared in the parent scope. - There is a third category of variables, marked as
common
. This is much likepublic
but they cannot directly see anyprivate
variables. This is a modifier that is not relevant in this context but included for completeness. It is unique to Nutmug and mainly useful when defining classes. - As an alternative to putting
private
,public
orcommon
in front of the name, the declaration can be marked using the annotations@private
/@public
/@common
.
Here is a simple example which could be written as a let
:
block
x := ref(initial)
public countup := fun(): x!, x! <-- $$ + 1 end
endblock
And here is a more elaborate example that shows how you can be selective in what is and is not visible outside the block. This is more awkward to turn into a let expression.
block
base_value := fetch_base_value()
public initial := calcuate_initial_value( base_value, 0 )
x := ref(initial)
public countup := fun(): x!, x! <-- $$ + 1 end
end
Files as block scopes
There are a couple of other block scopes in Nutmeg. Each compiled file forms a block scope with public default. This means it is possible to have private top-level definitions that are hidden from the rest of the program. e.g.
def factorial( n ):
fact( n, 1 )
enddef
@private
def fact( n, sofar ) =>>
if n <= 1:
sofar
else:
fact( n-1, n*sofar )
endif
enddef
Note that the default visibility for files is public
rather than private
.
Classes as Block Scope
Class definitions also introduce block scopes with a default of public
.