210 lines
3.7 KiB
PHP
210 lines
3.7 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace alveolata\structures;
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @template type_element
|
||
|
*/
|
||
|
class struct_subject_list
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* @var array {list<§type_element>}
|
||
|
*/
|
||
|
public $elements;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @param array $elements {list<§element>}
|
||
|
*/
|
||
|
public function __construct(
|
||
|
array $elements
|
||
|
)
|
||
|
{
|
||
|
$this->elements = $elements;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @template type_element
|
||
|
* @param array $elements {list<§element>}
|
||
|
* @return struct_subject_list<type_element>
|
||
|
*/
|
||
|
function list_make(
|
||
|
array $elements = []
|
||
|
) : struct_subject_list
|
||
|
{
|
||
|
return (new struct_subject_list($elements));
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @template type_element
|
||
|
* @param struct_subject_list<type_element> $subject
|
||
|
* @return int
|
||
|
*/
|
||
|
function list_length(
|
||
|
struct_subject_list $subject
|
||
|
) : int
|
||
|
{
|
||
|
return count($subject->elements);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @template type_element
|
||
|
* @param struct_subject_list<type_element> $subject
|
||
|
* @param int $index
|
||
|
* @return type_element
|
||
|
* @throws \Exception if index out of range
|
||
|
*/
|
||
|
function list_get(
|
||
|
struct_subject_list $subject,
|
||
|
int $index
|
||
|
)
|
||
|
{
|
||
|
if (! (($index >= 0) && ($index < list_lengt($subject)))) {
|
||
|
throw (new \Exception('index out of range'));
|
||
|
}
|
||
|
else {
|
||
|
return $subject->elements[$index];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @template type_element
|
||
|
* @param struct_subject_list<type_element> $subject
|
||
|
* @param type_element $element
|
||
|
*/
|
||
|
function list_add(
|
||
|
struct_subject_list $subject,
|
||
|
$element
|
||
|
) : void
|
||
|
{
|
||
|
array_push($subject->elements, $element);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @template type_element
|
||
|
* @param struct_subject_list<type_element> $subject
|
||
|
* @param \Closure $procedure {function<§type_element,void>}
|
||
|
*/
|
||
|
function list_iterate(
|
||
|
struct_subject_list $subject,
|
||
|
\Closure $procedure
|
||
|
) : void
|
||
|
{
|
||
|
foreach ($subject->elements as $element) {
|
||
|
$procedure($element);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @template type_element
|
||
|
* @param struct_subject_list<type_element> $subject
|
||
|
* @param \Closure $predicate {function<§type_element,boolean>}
|
||
|
* @return struct_subject_list<type_element>
|
||
|
*/
|
||
|
function list_filter(
|
||
|
struct_subject_list $subject,
|
||
|
\Closure $predicate
|
||
|
) : struct_subject_list
|
||
|
{
|
||
|
return (
|
||
|
new struct_subject_list(
|
||
|
array_values(
|
||
|
array_filter(
|
||
|
$subject->elements,
|
||
|
$predicate
|
||
|
)
|
||
|
)
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @template type_element_from
|
||
|
* @template type_element_to
|
||
|
* @param struct_subject_list<type_element_from> $subject
|
||
|
* @param \Closure $transformation {function<§type_element_from,§type_element_to>}
|
||
|
* @return struct_subject_list<type_element_to>
|
||
|
*/
|
||
|
function list_map(
|
||
|
struct_subject_list $subject,
|
||
|
\Closure $transformation
|
||
|
) : struct_subject_list
|
||
|
{
|
||
|
return (
|
||
|
new struct_subject_list(
|
||
|
array_map(
|
||
|
$transformation,
|
||
|
$subject->elements
|
||
|
)
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @template type_element
|
||
|
* @template type_result
|
||
|
* @param struct_subject_list<type_element> $subject
|
||
|
* @param type_result $start
|
||
|
* @param \Closure $aggregation function<§type_result,§type_element,§type_result>
|
||
|
* @return type_result
|
||
|
*/
|
||
|
function list_reduce(
|
||
|
struct_subject_list $subject,
|
||
|
$start,
|
||
|
\Closure $aggregation
|
||
|
)
|
||
|
{
|
||
|
return array_reduce(
|
||
|
$subject->element,
|
||
|
$aggregation,
|
||
|
$start
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @template type_element_1
|
||
|
* @template type_element_2
|
||
|
* @param \Closure $collate_element {function<type_element_1,type_element_2>}
|
||
|
* @param struct_subject_list<type_element_1>
|
||
|
* @param struct_subject_list<type_element_2>
|
||
|
* @return bool
|
||
|
*/
|
||
|
function list_collate(
|
||
|
\Closure $collate_element,
|
||
|
struct_subject_list $list_1,
|
||
|
struct_subject_list $list_2
|
||
|
) : bool
|
||
|
{
|
||
|
$length_1 = list_length($list_1);
|
||
|
$length_2 = list_length($list_2);
|
||
|
if (! ($length_1 === $length_2)) {
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
for ($index = 0; $index < $length_1; $index += 1) {
|
||
|
$element_1 = $list_1->elements[$index];
|
||
|
$element_2 = $list_2->elements[$index];
|
||
|
if (! $collate_element($element_1, $element_2)) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
?>
|