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.
All transforms methods expect to iterate over sequences, see https://www.lua.org/manual/5.2/manual.html#3.4.6
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.
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.
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
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.
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:
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
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
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}