Indentantions and layouts¶
Arza is indentation “aware” language
If you are familiar with a language like Python that also is whitespace sensitive, be aware that that the rules for indentation in Arza are subtly different.
Arza syntax very similar to F# light syntax where indentation used as statement and expression delimiter but instead of using simple dedents and indents like in Python, Arza uses code layouts to determine block borders
// layout is similar to pythons four space indent
fun f(x) =
1
2
// layout begins straight after = token
fun f(x) = 1
2
// this would be a syntax error
fun f(x) = 1
2
if x == 1 then
2
else 3
fun add
| (1, 2) = 3
| (x, y) = x + y
match x
| True = False
| False =
True
There are special rules for operators to continue expressions from line above, which differs from F# syntax and more similar to Ruby syntax
fun f() =
1 +
2 +
3
// returns 6
However this technique creates problem with ambidextra operators (operators having have both prefix and infix binding powers) Examples of such operators are - and (
To resolve parse conflicts Arza uses new lines as terminators
fun f() =
//lambda expression
((x, y) -> x + y)
// parser treats `(` as prefix expression because of new line
(1, 41)
f() == (1, 41)
fun f2() =
// parser treats `(` as infix expression and interprets
// this expression as call to lambda with arguments (1, 41)
((x, y) -> x + y)(1, 41)
f2() == 42
If you do not like to use indentation aware syntax at all, you can enclose any block in ( and )
You can enclose in ( and ) almost any syntax construct and use free code layout without worrying about whitespaces.
(fun f() =
1
+
2 + 3)
(interface Map
put
(key, value, Map)
at
(key,
Map)
)
If you need to use nested statements inside such free layout you must enclose each of them in ()
// Nine billion names of God the Integer
fun nbn () =
string:join(
seq:map(
fun(n) =
string:join_cast(
seq:map(
(fun (g) =
//let in block enclosed in ()
(let
(fun _loop (n, g) =
// if block enclosed in ()
(if g == 1 or n < g then 1
else
seq:foldl(
// fun block enclosed in ()
(fun (q, res) =
// if block enclosed in ()
(if q > n - g then
res
else
res + _loop(n-g, q)
)
),
1,
list:range(2, g)
)
)
)
in _loop(n, g)
)
),
list:range(1, n)
),
" "
),
list:range(1, 25)
),
"\n"
)
However because it is common pattern to use if or match expression inside function call there are special support for such syntax
add(match x
| #one = 1
| #two = 2
//here comma terminates free layout and there are no need to enclose match in ()
, 2)
add(match x
| #one = 1
| val of Float =
// but nested expressions must be enclosed
(if val < 0.0 then abs(val)
else val)
//here comma terminates free layout and there are no need to enclose match in ()
, 2)