ava/notes/expressions.md

100 lines
1.8 KiB
Markdown

# Expressions
_Expressions_ are the basis of programming in Ava. An expression is some code
that will produce a _value_ when evaluated.
## Syntax
Functions contain expressions. Expressions take the form of:
- Literal Values
- Variable Definitions
- Variable References
- Function Calls
- Control Structures
## Control Structures
### If Then
The `if/then` expression expects an expression that returns a _Boolean Value_.
That expression is evaluated. If it evaluates to `true`, the `then` expression
is evaluated. Otherwise the `else` expression is evaluated.
```
if <boolean expr> then <expr> else <expr>
```
### Match
```
match <expr>
case <pattern> => <expr>
end match
```
### Do/Return
The `do/return` expression allows for imperative composition of monadic
expressions. It works with any types that are members of `Monad` or `BiMonad`.
#### Do/Return for Monad
Each step of the `do` is defined by an expression that produces a Monad. The
syntax desugars to `fmap` calls, where `return` is a `map` call.
```
fn foo: () => Option[Int32]
1
end fn
fn bar: () => Option[Int32]
2
end fn
fn baz: () => Option[Int32]
3
end fn
let example: Option[Int32] :=
do
x <- foo()
y <- bar()
_ <- baz()
return
x + y
end do
assert(example == Some(3))
```
#### Do/Return for BiMonad
The `BiMonad` is right biased, where the "left" side is assumed to represent
some error case. The typical use case for this behavior is the `IO[E, A]` type.
```
fn foo: () => IO[String, Int32]
sync(1)
end fn
fn bar: () => IO[String, Int32]
sync(2)
end fn
fn baz: () => IO[String, Int32]
sync(3)
end fn
let program: IO[String, Int32] :=
do
x <- foo()
y <- bar()
_ <- baz()
return
x + y
end do
program ->
sum => assert(sum == 3)
```