Transforms ================= The transforms library is set of utilities for working with indexed tables. It provides highly reusable special iterators that are at the core of `text` and `sh` command parsing. ===== Transforms API ===== * **Transforms work on _sequences_** All transforms methods expect to iterate over sequences, see https://www.lua.org/manual/5.2/manual.html#3.4.6 * **first and last** All `first` and `last` arguments act in the same fashion as the `first` and `last` arguments used in `string` methods such as `string.sub`. That is, it accepts negative values, which work relative from the end. `first` (when optional) defaults to 1, and `last` defaults to -1. * **The Predicate** All transform methods that take a predicate use this predicate defintiion: * `predicate(element: value, index: number, tbl: table): number, number` This predicate is called in sequence on each index in `tbl`. `element` is the value at `tbl[index]`. Generally, predicate methods ignore `index` and `tbl`, and only process `element`. But some predicates may need to check values in `tbl` before or after `index`. **Important** to note that the `tbl` passed to the `predicate` is actually a _**view**_ of the original table passed to the transforms api. This _**view**_ is not a natural sequence but instead only returns values from `tbl` within the [`first`, `last`] range. In other words, the predicate handles a "set of elements" and returns parameters indicating the satisfied condition. * **Set of Elements** The "set of elements" refers to either: A) The single `element` passed to the predicate. This is the same value at `tbl[index]` or B) The sequence of elements starting at `index` in `tbl`. The predicate may iterate from `index` for as many elements it needs to check, until `#tbl` * **Return Parameters** Possible values for the return parameters 1 `false` or `nil` if the predicate is not satisfied with the set of elements. `index` to indicate success. It should simply return the same index given, which is the starting index of the set of elements 2. The size of the set of elements that satisfied the predicate, or `nil` Some tranform methods may specify that the 2nd return is optional, such as `transforms.first()` Some transform methods may specify alternative predicate types that can be used, such as tables or strings. These predicate usages are specific to those methods and defined within the method details here. ==== Methods ==== * `transforms.sub(tbl: table, first: number, last: number or nil): table` Behaves similarly to `string.sub`. Returns a sub table of `tbl` from `first` to `last`. * `transforms.first(tbl: table, predicate: function or table, first: number or nil, last: number or nil): number, number` Returns the first index in `tbl` (between indexes `first` and `last`, inclusively) where `predicate` is satisfied. The 2nd return is also the ending index of the match. General examples will have the same two values returned, i.e. a match of length 1. The `predicate` can (optionally) return a 2nd return value to indicate the size of the match. In the case that `predicate` is a table, `transforms.first()` returns the starting and ending index of the first matching sub table in `tbl` that matches ANY one of the tables in `predicate`. Examples: ```lua local tx = require("transforms") print( tx.first ( { 1, 1, 3, 2, 4, 7 }, function(e, i, tbl) local evens = 0 for i=i,#tbl do if tbl[i] % 2 == 0 then evens = evens + 1 else break end end return evens > 0, evens end)) ``` Output ``` 4 5 ``` ```lua local tx = require("transforms") print( tx.first ( { 1, 1, 3, 2, 4, 7 }, { {1, 2}, {3, 2, 4} }) ) ``` Output ``` 3 5 ``` * `transforms.partition(tbl: table, partioner: function, first: number or nil, last: number or nil): table of tables` Returns a list of sub lists from `tbl`, generated by `partioner` within the range from `first` to `last`. `partioner` is a `predicate` function, defined above. The `index` parameter passed to the `partitioner` will skip ranges, i.e. it will increase by `n` where `n` is the size of the partition. The `partitioner` predicate for this method must return the starting AND ending index of satisfied element sets. Again, see the `predicate` info above. * `transforms.begins(tbl: table, sub: table, first: number or nil, last: number or nil)` Returns true if the subset of `tbl` from `first` to `last` fully composes `v` aligned at the first index. Assuming `first` and `last` have been adjusted for negative wrap around, that is to say: `v[1] == tbl[first + 0]` `v[2] == tbl[first + 1]` ... `v[#v] == tbl[first + #v - 1]` Where `first + #v - 1` is within the bounds of `[first, last]` of `tbl`. * `transforms.foreach(tbl: table, adapter: function, first: number or nil, last: number or nil)` Returns an adaptation of each element in `tbl` from `first` to `last`. Any `nil` result of the `adapter` is ignored, and not appended to the result. The `adapter` follows the `predicate` signature except for the handling of the return values * **Adapter Returns** The simple case is to return a single value. E.g. `tx.foreach({'a', 'b', 'c'}, string.upper)` would return `{'A', 'B', 'C'}`. The adapter can return `nil` to skip a value. E.g. `tx.foreach({'1', 'foobar', '2'}, function(n) return tonumber(n) end)` would return `{1, 2}`. But the `adapter` can return a second value that is used in place of the next sequence number. E.g. `tx.foreach({'1','foobar','3'},function(n,i) return tonumber(n), tostring(i) end)` would return `{["1"]=1, ["3"]=3}` Contents ----------- {{page>api:contents&noheader&noeditbutton&nouser&nofooter}}