from _erg_control import then__ from _erg_range import Range from _erg_nat import NatMut from _erg_int import IntMut from _erg_contains_operator import contains_operator from _erg_result import is_ok from _erg_result import Error class Array(list): def try_new(arr): # -> Result[Array] if isinstance(arr, list): return Array(arr) else: return Error("not a list") def generic_try_new(arr, cls = None): # -> Result[Array] if cls is None: return Array.try_new(arr) else: elem_t = cls.__args__[0] elems = [] for elem in arr: # TODO: nested check elem = elem_t.try_new(elem) if is_ok(elem): elems.append(elem) else: return Error("not a " + str(elem_t)) return Array(elems) def dedup(self, same_bucket=None): if same_bucket is None: return Array(list(set(self))) else: removes = [] for lhs, rhs in zip(self, self[1:]): if same_bucket(lhs, rhs): removes.append(lhs) for remove in removes: self.remove(remove) return self def get(self, index, default=None): try: return self[index] except IndexError: return default def push(self, value): self.append(value) return self def partition(self, f): return Array(list(filter(f, self))), Array( list(filter(lambda x: not f(x), self)) ) def __mul__(self, n): return then__(list.__mul__(self, n), Array) def __getitem__(self, index_or_slice): if isinstance(index_or_slice, slice): return Array(list.__getitem__(self, index_or_slice)) elif isinstance(index_or_slice, NatMut) or isinstance(index_or_slice, IntMut): return list.__getitem__(self, int(index_or_slice)) elif isinstance(index_or_slice, Range): return Array(list.__getitem__(self, index_or_slice.into_slice())) else: return list.__getitem__(self, index_or_slice) def __hash__(self): return hash(tuple(self)) def update(self, f): self = Array(f(self)) def type_check(self, t: type) -> bool: if isinstance(t, list): if len(t) < len(self): return False for (inner_t, elem) in zip(t, self): if not contains_operator(inner_t, elem): return False return True elif isinstance(t, set): return self in t elif not hasattr(t, "__args__"): return isinstance(self, t) elem_t = t.__args__[0] l = None if len(t.__args__) != 2 else t.__args__[1] if l is not None and l != len(self): return False for elem in self: if not contains_operator(elem_t, elem): return False return True def update_nth(self, index, f): self[index] = f(self[index]) class UnsizedArray: elem: object def __init__(self, elem): self.elem = elem