<?php

declare(strict_types=1);

namespace Psl\Math;

use Closure;

/**
 * Returns the largest element of the given iterable, or null if the
 * iterable is empty.
 *
 * The value for comparison is determined by the given function.
 *
 * In the case of duplicate values, later values overwrite previous ones.
 *
 * @template T
 *
 * @param iterable<T> $numbers
 * @param (Closure(T): numeric) $numeric_function
 *
 * @return T|null
 */
function max_by(iterable $numbers, Closure $numeric_function): mixed
{
    $max = null;
    $max_num = null;
    foreach ($numbers as $value) {
        $value_num = $numeric_function($value);
        if (null === $max_num || $value_num >= $max_num) {
            $max = $value;
            $max_num = $value_num;
        }
    }

    return $max;
}
