--!strict --!optimize 2 local Array = {} Array.__index = Array type constructor = { inner: {T} } export type Array = typeof(setmetatable({} :: constructor, Array)) type FnCall = (T, number, Array) -> R function Array.new(from: {T}?): Array return setmetatable({ inner = from or {} }, Array) end function Array:table(): {T} return self.inner end function Array:pop(): T? return table.remove(self.inner, #self.inner) end function Array:concat(sep: string?, i: number?, j: number?): string return table.concat(self.inner, sep, i, j) end function Array:clone(): Array return Array.new(table.clone(self.inner)) end function Array:len(): number return #self.inner end function Array:get(index: I): T? return self.inner[index] end function Array:push(...: T): () for _, val: T in {...} do table.insert(self.inner, val) end end function Array:foreach(callbackFn: FnCall): Array for ind: number, val: T in self.inner do callbackFn(val, ind, self) end return self end function Array:map(callbackFn: FnCall): Array local n: {M} = {} for ind: number, val: T in self.inner do table.insert(n, callbackFn(val, ind, self)) end return Array.new(n) end function Array:filter(callbackFn: FnCall): Array local n: {T} = {} for ind: number, val: T in self.inner do if callbackFn(val, ind, self) then table.insert(n, val) end end return Array.new(n) end function Array:binary_search(x: T): T? local size = #self.inner if size == 0 then return nil end local base = 1 while base < size do size -= bit32.rshift(base + size, 1) end return nil end function Array:debug_display(): string return self:map(function(val: T, ind: number) return ind .. ": " .. tostring(val) .. (ind ~= self:len() and ", " or "") end):concat() end return Array