Overview

Sometimes it is important to expose a variable or a portion of a data structure to a different piece of code that needs to mutate it, but doesn’t need to know where the data lives. On the surface, doing so might seem difficult. Consider the following example:

Dict is int->>str->>str = (1->($a->"hello", $b->"world")). 
Dict 1 $a -> "goodbye".

In this example, one element is being mutated inside a subdictionary of a dictionary. To perform this operation inside a well-written function, we would like to pass some kind of a “pointer” to the field "hello" into the function, rather than tell the function where to find the field. You can do so using the MUFL’s references, as illustrated in this example:

fn MutateIt (theRef:&(str+)) { 
    #theRef->"goodbye". // will mutate the value to which reference 'theRef' is pointing
}

Dict is int->>str->>str = (1->($a->"hello", $b->"world")). 
MutateIt &(Dict 1 $a). // will pass reference to 'Dict 1 $a' into function 'MutateIt'

Here’s another example of using references:

A = 1. 
B = &A. // construct a reference to 'A'
#B -> 2. // Mutate 'A' via reference

Map = ("A"->"A_halo", "B"->"B_world" ). 
Ref = &(Map "A"). 
#Ref->"A_hello". 
// Map is now ("A"->"A_hello", "B"->"B_world").

Only globally-scoped variables can generate a reference. Variables declared locally inside functions can be mutated, but one cannot create a reference to them.

References work symbolically. They are not actual pointers, but rather indicate a path the evaluator must take to get to the given value. Some programming language call this concept a “weak” reference because the existance of the reference does not guarantee there is a value it references.

This is illustrated in the following example:

A is any->>any = (,). 
B = &(A 1 2 3 4). // This reference cannot be used yet because dictionary A does not have the given element path. 
A 1 -> (2->(3->(4->5))). // We have now created an element for which B is a valid reference
#B->5. 
_print (A 1 2 3 4). // will print '5'