Declarations - Spicery/Nutmeg GitHub Wiki

Nutmeg directly supports three different ways to declare variables, as var, val or const.

var x := 0      ### Assignable, cannot be used at top-level, not visible in nested scopes
val y := 1      ### Not-assignable, read-only - default!
const z := 2    ### Only binds to const (recursively immutable) values

The var keyword is required if you want to assign to a variable using. As you may have guessed, var is short for 'variable'. These variables are quite restricted. Firstly, var variables are not usable in nested functions. Secondly, top-level variables cannot be declared as var. Since they would not be accessible in any function, a top-level var would be of limited use and we prefer to give the reader the assurance that top-level variables are permanently bound to their initial values. Counter-intuitively, loop variables do not need to be var-declared because each time around a loop you get a new variable (i.e. bound not assigned).

The val keyword restricts the new variable to be read-only. Any attempts to assign to the variable will generate a compiler error. val is the default declaration when there is no explicit declaration. This is because we believe that using a variable is unremarkable but, in contrast, assigning to a variable is an important implementation decision that readers should have their attention drawn to. The val keyword is short for 'value' because these variables cannot change their value.

The const keyword goes even further. Not only can it not be assigned to, the new variable can only be bound to values that are immutable all the way down. In other words, any reference you can reach from a const value is guaranteed to also be immutable. This is a vital property that functional programming enjoys and Nutmeg aims to fully support functional programming. In practical terms, such fully-immutable values allow for completely unrestricted store sharing (aliasing) without complications.

If you are writing a lot of pure functions, it is tedious to keep writing const in front of every variable declaration. So Nutmeg allows you to define functions with an alternative syntax function rather than def. A key difference is that the all declarations inside a function are treated as const.

function f( x ) =>> 
    x + 1           ### f and x are both consts
endfunction   

as always we can shorten this using colons and end

function f( x ):
    x + 1
end

It is worth being aware that crossing from imperative to functional code may require the compiler to plant immutability checks. These are a small overhead and rarely a concern.

Const Functions

Immutability is a simple criteria for most datatypes. But a functions are a complex but important special case. The subtle answer is that a const function cannot refer to a mutable object, either directly or indirectly via objects it does reference. However, the invocation of a const function will typically instantiate local variables and these may reference mutable store. So we have to distinguish between the function-object itself and the invocation.

The most straightforward way to visualise this is to imagine tracing the reachability graph from the function object. By contrast, when a function is called, not only can it potentially reach all the objects in that graph it can additionally reference the arguments that are passed in and also any objects that are returned by reading from devices. It turns out that both of these are important concepts in Nutmeg, However the mutability of a function is not dependent on the runtime arguments.

Const Classes

Another special and similar case is that of a class definition. Analogously to functions, we should distinguish between the class-object and the instance of a class. A const class does not refer to any mutable store, directly or indirectly. However when an instance is constructed it may be passed mutable objects and its methods may be passed mutable arguments.