Simple Guards

nil is used throughout Minilang to denote the absence of any other value. This includes the initial values of variables or object fields before assignment, indexing a map or list with a missing key or index and the result of binary comparisons which are logically false.

1var X
2X :> nil
3let L := [1, 2, 3]
4L[4] :> nil
5let M := {"A" is 1, "B" is 2}
6M["C"] :> nil
72 < 1 :> nil

As a result, it is often required to check the result of an expression for nil before using the result in a function call.

1let M := {"A" is [1, 2], "B" is [3, 4]}
2M["A"][1] :> 1
3M["C"][1] :> MethodError: no method found for [](nil, int32)
5if let T := M["A"] then T[1] end :> 1
6if let T := M["C"] then T[1] end :> nil

Minilang provides a shorthand for this type of check using guarded arguments. A simple guarded argument consists of an empty pair of braces {} following an expression in a function call.

If the expression in a simple guarded argument evaluates to nil then the innermost function call containing the guarded argument evaluates immediately to nil without invoking the called function.

1let M := {"A" is [1, 2], "B" is [3, 4]}
2M["A"]{}[1] :> 1
3M["C"]{}[1] :> nil

General Guards

Other than simply checking for nil, guarded arguments can also check their preceeding expression for arbitrarily complex conditions by including another expression inside the braces. Within the braces, the keyword it refers to the value of the preceeding expression.

1for I in 1 .. 10 do
2   print("I = ", I{2 | it}, "\n")
I = 2
I = 4
I = 6
I = 8
I = 10