---@class Iter ---@operator call: fun(v: any, ...): Iter local Iter = {} Iter.__index = Iter ---@generic T ---@param n function ---@param t T ---@param i integer function Iter.new(n, t, i) local self = {} self.n = n self.t = t self.i = i return setmetatable(self, Iter) end function Iter:to() local final = {} for k, v in self.n, self.t, self.i do final[k] = v end return final end ---@generic K, V, R ---@param f fun(k: K, v: V): R function Iter:map(f) local new = {} for k, v in self.n, self.t, self.i do local result = f(k, v) if result ~= nil then table.insert(new, result) end end return Iter.new(self.n, new, self.i) end ---@generic K, V, R ---@param f fun(k: K, v: V): R function Iter:filter(f) for k, v in self.n, self.t, self.i do if not f(k, v) then table.remove(self.t, k) end end return self end ---@generic K, V ---@param f fun(k: K, v: V) function Iter:each(f) for k, v in self.n, self.t, self.i do f(k, v) end end ---@generic K, V, R ---@param init R ---@param f fun(acc: R, k: K, v: V): R? ---@return R function Iter:fold(init, f) local acc = init for k, v in self.n, self.t, self.i do local result = f(acc, k, v) if result ~= nil then acc = result end end return acc end ---@generic K, V ---@param f fun(k: K, v: V): K, V function Iter:mapattrs(f) local new = {} for k, v in self.n, self.t, self.i do local _k, _v = f(k, v) if _k ~= nil then new[_k] = _v end end return Iter.new(self.n, new, self.i) end ---@generic V ---@param f fun(a: V, b: V): boolean returns true when the first item is less --- than the second function Iter:sort(f) local new = {} for k, v in self.n, self.t, self.i do new[k] = v end table.sort(new, f) return Iter.new(self.n, new, self.i) end ---@param n integer function Iter:skip(n) self.i = (self.i or 1) + n return self end ---@param j integer function Iter:take(j) local new = {} local i = 0 for k, v in self.n, self.t, self.i do i = i + 1 if i > j then break end new[k] = v end return Iter.new(self.n, new, self.i) end ---@param lst any[] function Iter.lst(lst) return Iter.new(ipairs(lst)) end ---@param tbl table function Iter.tbl(tbl) return Iter.new(pairs(tbl)) end ---@param str string function Iter.str(str) local it = Iter.new( setmetatable({ i = -1 }, { __call = function(self, s, i) if self.i == -1 then self.i = i end local idx = self.i self.i = self.i + 1 if idx > #s then self.i = -1 return end return idx, s:sub(idx, idx) end, }), str, 1 ) local lst = it:to() return Iter.lst(lst) end return Iter