} * @author Christian Fraß */ function sequence( int $length ) : array { return ( ($length <= 0) ? [] : array_merge(sequence($length-1), [$length-1]) ); } /** * @param array $list1 {list<§x>} * @param array $list2 {list<§x>} * @return array {list<§x>} * @author Christian Fraß */ function concat( array $list1, array $list2 ) : array { return array_merge($list1, $list2); } /** * @param array $list {list<§x>} * @param \Closure $predicate {function<§x,boolean>} * @return array {list<§x>} * @author Christian Fraß */ function filter( array $list, \Closure $predicate ) : array { $list_ = []; foreach ($list as $value) { if ($predicate($value)) { array_push($list_, $value); } } return $list_; } /** * @param array $list {list<§x>} * @param \Closure $transformator {function<§x,§y>} * @return array {list<§y>} * @author Christian Fraß */ function map( array $list, \Closure $transformator ) : array { $list_ = []; foreach ($list as $value) { $value_ = $transformator($value); array_push($list_, $value_); } return $list_; } /** * @param array $list {list<§x>} * @param mixed $start {§y} * @param \Closure $aggregator {function<§y,§x,§y>} * @return mixed {§y} * @author Christian Fraß */ function reduce_left( array $list, $start, \Closure $aggregator ) { $result = $start; foreach ($list as $current) { $result = $aggregator($result, $current); } return $result; } /** * @param array $list {list<§x>} * @param mixed $start {§y} * @param \Closure $aggregator {function<§x,§y,§y>} * @return mixed {§y} * @author Christian Fraß */ function reduce_right( array $list, $start, \Closure $aggregator ) { $result = $start; foreach (array_reverse($list) as $current) { $result = $aggregator($current, $result); } return $result; } /** * @param array $list {list<§x>} * @param mixed $start {§y} * @param \Closure $aggregator {function<§y,§x,§y>} * @return mixed {§y} * @author Christian Fraß */ function reduce( array $list, $start, \Closure $aggregator ) { return reduce_left($list, $start, $aggregator); } /** * @param array $list {list<§x>} * @param \Closure $predicate {function<§x,bool>} * @return bool {boolean} * @author Christian Fraß */ function some( array $list, \Closure $predicate ) : bool { foreach ($list as $current) { if ($predicate($current)) { return true; } } return false; } /** * @param array $list {list<§x>} * @param \Closure $predicate {function<§x,bool>} * @return bool {boolean} * @author Christian Fraß */ function every( array $list, \Closure $predicate ) : bool { foreach ($list as $current) { if (! $predicate($current)) { return false; } } return true; } /** * @param array $list1 {list<§x>} * @param array $list2 {list<§y>} * @param bool $cut {boolean} whether to take the least length in case the lists have different lengths * @return array {list>} * @throw \Exception if lists have different lengths and $cut = false * @author Christian Fraß */ function zip( array $list1, array $list2, bool $cut = true ) : array { $l1 = count($list1); $l2 = count($list2); if (! ($l1 === $l2)) { if (! $cut) { throw (new \Exception('lists have different lengths')); } else { $length = $l1; } } else { $length = min($l1, $l2); } $list3 = []; for ($index = 0; $index < $length; $index += 1) { $pair = [ 'first' => $list1[$index], 'second' => $list2[$index], ]; array_push($list3, $pair); } return $list3; } /** * @param array $list {list<§x>} * @param \Closure $order {function<§x,§x,boolean>} * @return array {list<§x>} * @throws \Exception if the sorting fails * @author Christian Fraß */ function sort( array $list, \Closure $order = null ) : array { if (is_null($order)) { $order = (function ($x, $y) {return ($x <= $y);}); } $copy = array_map(function ($x) {return $x;}, $list); $successful = usort( $copy, function ($x, $y) use ($order) : int { return ($order($x, $y) ? (-1) : (+1)); } ); if (! $successful) { throw (new \Exception('alveolata_list_sort_failed')); } else { return $copy; } } /** * @param array $list {list<§x>} * @param \Closure $collation {function<§x,§x,boolean>} * @return array {list>} */ function group( array $list, \Closure $collation ) : array { $groups = []; foreach ($list as $element) { $found = false; foreach ($groups as &$group) { if ($collation($group[0], $element)) { array_push($group, $element); $found = true; break; } } unset($group); if (! $found) { $group = [$element]; array_push($groups, $group); } } return $groups; } /** * @param array $x {list} * @param array $y {list} * @param ?array $options { * ( * null * | * record< * ?combinator:function,any>, * > * ) * } * @return array {list>} */ function product( array $x, array $y, ?array $options = null ) : array { $options = \array_merge( [ 'combinator' => (fn($u, $v) => [$u, $v]) ], ($options ?? []) ); $z = []; foreach ($x as $u) { foreach ($y as $v) { \array_push($z, $options['combinator']($u, $v)); } } return $z; } ?>