The Boring Programming Language (Boring-Lang) is an attempt to create an easy, productive, general purpose programming language that makes as few interesting choices as possible while still being in line with modern concepts in programming languages.
All variables are immutable by default, to make them mutable use the `mut` keyword. Once a variable becomes immutable it cannot become mutable again. If you need it to become mutable, either implement the `clone` trait, or simply create a new one with the same data.
Context is an exceptionally useful feature in golang, but a common complaint is that:
1. Because it works as an arbitrary map, it can be used to pass arguments into a function that aren't explicitly stated.
2. It is used for both passing context parameters and cancellation, two fundamentally different tasks that have no reason to be in the same object.
The boring standard library solves this by using parametric polymorphism. Context is by default an empty object passed through the chain, and each function/set of context parameters is an additional trait condition applied at compile time.
Boring uses function modifiers to implement functionality like `async/await` and `coroutines`. These function by [rewriting the code into a state machine](https://tmandry.gitlab.io/blog/posts/optimizing-await-1/) prior to compilation. The table below describes the modifiers currently available.
Similar to python, folders/files represent the `.` seperated import path, but relative imports are *not* supported. Exported values must be marked with `pub`. All imports take the form:
`if` is an expression in boring-lang, with the last expression in a block being the return value. If the block ends in a statement rather than an expression, Optional None is returned.
```
let a = if true {
4
} else {
2
}
// a == 4
let b = if false {
2
}
// b is an Optional<Int32> with value None.
```
Conditions do not require parenthesis and *must* evaluate to the Boolean type.
### Loops
Boring-lang supports `for` and `while` loops, with `for` having an `async` variant. `while` loops require an expression of Boolean type, while `for` loops require an expression that implements the `Iter` or `AIter` traits.
`continue` and `break` work similar to other languages.
```
while true {
break // do nothing
}
for i in range(100) {
continue // do nothing
}
```
### `with`
`with` and `async with` blocks are similar to the python statement with the same name. But unlike the python version, `with` blocks are expressions. `with` blocks take in an expression that implements the `With` or `AWith` trait, and execute a block that *may* return a result (non-result returns are assumed success).
```
// commits on success, aborts on error.
// transation.aexit may just return an error as a pass-through after aborting,
// but it may also transform it into another error adding context.
return async with db.transation(ctx) as t {
await t.insert(ctx, record) // returns result type
}
```
### `return`
`return` statements exit a function early, returning the given value. They are purely optional as the last expression in a function will automatically return its value.
### `match`
`match` expressions provide pattern matching, similar to a `C` switch statement.