# A language based on an age-old CS lie
##### If you bound your execution, you can lie and say it's O(1).
Bounded execution. All things **must** come to an end.
If a loop mutates *memory* (note: **not** has a side-effect) that escapes its lexical
context, it must have an upper bound. Functions that capture their context and return a
reference to it (i.e. closures) cannot allocate, but they can return functions that can.
This is the basis of iterators and general purpose looping.
In the below example, a type definition, denoted with the `type` keyword is created that
*aliases* another type with a known bound. The number in-between the `{}` is the upper
bounds for this type.
```
type path = os-str{4096};
```
While having a maximum *size* is important the real benefit comes into play for looping:
```
path = "/home/noah/text.md"
loop each(path) => c { // => 4096 * <loop allocation size>
print(c)
}
```
The implementation of a `each()` might look something like this:
```
defn each(arr: [?], start: isize = 0 ,inc: isize = 1) {
i = start
ret fn() -> ? {
out = get(arr, i)
!i = i + inc // non-local assignment
ret out
}
}
defn pairs(coll: {?K, ?V}) {
kys = keys(coll)
ret fn () -> (?K, ?V) {
key = kys()
ret (key, get(coll, key))
}
}
// collections are special interleived arrays
defn keys(coll: {?K, ?v}) {
ret each(coll, inc=2)
}
```