An example program in A-Normal Form:
(
let x = 5 in
let y = ((+ 1) 2) in
if ((> x) y) then (x) else (y)
)
A program in A-Normal Form (ANF) is a block enclosed by parentheses.
A block begins with zero or more let-bindings and is followed by exactly one 'tail expression'.
A let-binding may have only simple expressions on the right-hand side.
The tail expression is the last line in a block.
The value of a block is equal to its tail expression.
Note that control flow, such as an if-expression, is only allowed in the tail position.
Basically, there are two ways to program:
1. Create step-by-step intermediate results and bind them to variables.
2. Create nested blocks to chain computations that way.
There are several keywords which have their own syntax:
| Operation |
Example |
Description |
| lambda | lambda x ((+ 1) x) | create a function of one variable, is allowed almost anywhere |
| let | (let x = 5 in ((* 2) x)) | define variables in a block |
| if | (if true then (4) else (8)) | selects between two blocks, only allowed at the end of a block |
There are also a number of built-in functions:
| Operation |
Example |
Description |
| ~ | (~ 5) | negative (note: tilde, not a minus sign) |
| + | ((+ 5) 2) | addition |
| - | ((- 5) 2) | subtraction |
| * | ((* 5) 2) | multiplication |
| / | ((/ 5) 2) | division |
| % | ((% 5) 2) | remainder after division |
| < | ((< 5) 2) | less than |
| > | ((> 5) 2) | greater than |
| <= | ((<= 5) 2) | less than or equal to |
| >= | ((>= 5) 2) | greater than or equal to |
| == | ((== 5) 2) | equal to |
| != | ((!= 5) 2) | unequal to |
| & | ((&& true) false) | logical and |
| | | ((|| true) false) | logical or |
| ! | (! true) | logical not |
A function can be called by writing the name of the function, followed by an argument.
Functions always take exactly one argument at a time.
If the function needs a second argument, you need to do another function application 'fn arg'.
This is why it is necessary to write: (+ 1) 2