# 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) } ```