hoist callback compilation out of transform closures
This commit is contained in:
parent
b48f28e9dc
commit
04c40087c2
@ -44,9 +44,9 @@ use function Kadet\Functional\compile;
|
|||||||
*/
|
*/
|
||||||
function map(callable $fn): \Closure
|
function map(callable $fn): \Closure
|
||||||
{
|
{
|
||||||
return static function (iterable $input) use ($fn): iterable {
|
$fn = callback($fn);
|
||||||
$fn = callback($fn);
|
|
||||||
|
|
||||||
|
return static function (iterable $input) use ($fn): iterable {
|
||||||
return keyedLike($input, (static function () use ($input, $fn) {
|
return keyedLike($input, (static function () use ($input, $fn) {
|
||||||
foreach ($input as $key => $value) {
|
foreach ($input as $key => $value) {
|
||||||
yield $key => $fn($value, $key);
|
yield $key => $fn($value, $key);
|
||||||
@ -69,9 +69,9 @@ function map(callable $fn): \Closure
|
|||||||
*/
|
*/
|
||||||
function filter(?callable $fn = null): \Closure
|
function filter(?callable $fn = null): \Closure
|
||||||
{
|
{
|
||||||
return static function (iterable $input) use ($fn): iterable {
|
$fn = $fn === null ? static fn ($value) => $value : callback($fn);
|
||||||
$fn = $fn === null ? static fn ($value) => $value : callback($fn);
|
|
||||||
|
|
||||||
|
return static function (iterable $input) use ($fn): iterable {
|
||||||
return keyedLike($input, (static function () use ($input, $fn) {
|
return keyedLike($input, (static function () use ($input, $fn) {
|
||||||
foreach ($input as $key => $value) {
|
foreach ($input as $key => $value) {
|
||||||
if ($fn($value, $key)) {
|
if ($fn($value, $key)) {
|
||||||
@ -94,10 +94,16 @@ function filter(?callable $fn = null): \Closure
|
|||||||
*/
|
*/
|
||||||
function reject(callable $fn): \Closure
|
function reject(callable $fn): \Closure
|
||||||
{
|
{
|
||||||
return static function (iterable $input) use ($fn): iterable {
|
$fn = callback($fn);
|
||||||
$fn = callback($fn);
|
|
||||||
|
|
||||||
return filter(static fn ($value, $key) => !$fn($value, $key))($input);
|
return static function (iterable $input) use ($fn): iterable {
|
||||||
|
return keyedLike($input, (static function () use ($input, $fn) {
|
||||||
|
foreach ($input as $key => $value) {
|
||||||
|
if (!$fn($value, $key)) {
|
||||||
|
yield $key => $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,9 +122,9 @@ function reject(callable $fn): \Closure
|
|||||||
*/
|
*/
|
||||||
function flatMap(callable $fn): \Closure
|
function flatMap(callable $fn): \Closure
|
||||||
{
|
{
|
||||||
return static function (iterable $input) use ($fn): iterable {
|
$fn = callback($fn);
|
||||||
$fn = callback($fn);
|
|
||||||
|
|
||||||
|
return static function (iterable $input) use ($fn): iterable {
|
||||||
return listLike($input, (static function () use ($input, $fn) {
|
return listLike($input, (static function () use ($input, $fn) {
|
||||||
foreach ($input as $key => $value) {
|
foreach ($input as $key => $value) {
|
||||||
$result = $fn($value, $key);
|
$result = $fn($value, $key);
|
||||||
@ -192,9 +198,10 @@ function unique(): \Closure
|
|||||||
*/
|
*/
|
||||||
function uniqueBy(callable $selector): \Closure
|
function uniqueBy(callable $selector): \Closure
|
||||||
{
|
{
|
||||||
|
$selector = callback($selector);
|
||||||
|
|
||||||
return static function (iterable $input) use ($selector): iterable {
|
return static function (iterable $input) use ($selector): iterable {
|
||||||
$selector = callback($selector);
|
$seen = seen();
|
||||||
$seen = seen();
|
|
||||||
|
|
||||||
return keyedLike($input, (static function () use ($input, $selector, $seen) {
|
return keyedLike($input, (static function () use ($input, $selector, $seen) {
|
||||||
foreach ($input as $key => $value) {
|
foreach ($input as $key => $value) {
|
||||||
@ -219,10 +226,10 @@ function uniqueBy(callable $selector): \Closure
|
|||||||
*/
|
*/
|
||||||
function sort(?callable $comparator = null): \Closure
|
function sort(?callable $comparator = null): \Closure
|
||||||
{
|
{
|
||||||
return static function (iterable $input) use ($comparator): iterable {
|
// Comparators always take two values, so they are compiled without the ($value, $key) adaptation.
|
||||||
// Comparators always take two values, so they are compiled without the ($value, $key) adaptation.
|
$comparator = $comparator === null ? static fn ($a, $b) => $a <=> $b : compile($comparator);
|
||||||
$comparator = $comparator === null ? static fn ($a, $b) => $a <=> $b : compile($comparator);
|
|
||||||
|
|
||||||
|
return static function (iterable $input) use ($comparator): iterable {
|
||||||
$entries = entries($input);
|
$entries = entries($input);
|
||||||
usort($entries, static fn ($a, $b) => $comparator($a[1], $b[1]));
|
usort($entries, static fn ($a, $b) => $comparator($a[1], $b[1]));
|
||||||
|
|
||||||
@ -245,9 +252,9 @@ function sort(?callable $comparator = null): \Closure
|
|||||||
*/
|
*/
|
||||||
function sortBy(callable $selector, bool $descending = false): \Closure
|
function sortBy(callable $selector, bool $descending = false): \Closure
|
||||||
{
|
{
|
||||||
return static function (iterable $input) use ($selector, $descending): iterable {
|
$selector = callback($selector);
|
||||||
$selector = callback($selector);
|
|
||||||
|
|
||||||
|
return static function (iterable $input) use ($selector, $descending): iterable {
|
||||||
$entries = [];
|
$entries = [];
|
||||||
foreach ($input as $key => $value) {
|
foreach ($input as $key => $value) {
|
||||||
$entries[] = [$key, $value, $selector($value, $key)];
|
$entries[] = [$key, $value, $selector($value, $key)];
|
||||||
@ -304,6 +311,10 @@ function slice(int $offset, ?int $length = null): \Closure
|
|||||||
*/
|
*/
|
||||||
function take(int $n): \Closure
|
function take(int $n): \Closure
|
||||||
{
|
{
|
||||||
|
if ($n < 0) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('take(): count must be >= 0, got %d', $n));
|
||||||
|
}
|
||||||
|
|
||||||
return slice(0, $n);
|
return slice(0, $n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,6 +325,10 @@ function take(int $n): \Closure
|
|||||||
*/
|
*/
|
||||||
function skip(int $n): \Closure
|
function skip(int $n): \Closure
|
||||||
{
|
{
|
||||||
|
if ($n < 0) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('skip(): count must be >= 0, got %d', $n));
|
||||||
|
}
|
||||||
|
|
||||||
return slice($n);
|
return slice($n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,9 +415,9 @@ function merge(iterable $other): \Closure
|
|||||||
*/
|
*/
|
||||||
function each(callable $fn): \Closure
|
function each(callable $fn): \Closure
|
||||||
{
|
{
|
||||||
return static function (iterable $input) use ($fn): iterable {
|
$fn = callback($fn);
|
||||||
$fn = callback($fn);
|
|
||||||
|
|
||||||
|
return static function (iterable $input) use ($fn): iterable {
|
||||||
$reusable = is_array($input) || $input instanceof \Ds\Seq || $input instanceof \Ds\Map || $input instanceof \Ds\Set;
|
$reusable = is_array($input) || $input instanceof \Ds\Seq || $input instanceof \Ds\Map || $input instanceof \Ds\Set;
|
||||||
if ($reusable) {
|
if ($reusable) {
|
||||||
foreach ($input as $key => $value) {
|
foreach ($input as $key => $value) {
|
||||||
|
|||||||
@ -300,6 +300,22 @@ class TransformsTest extends \PHPUnit\Framework\TestCase
|
|||||||
$this->assertSeq([2, 3], c\skip(1)(self::gen([1, 2, 3])));
|
$this->assertSeq([2, 3], c\skip(1)(self::gen([1, 2, 3])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testTakeRejectsNegativeCount()
|
||||||
|
{
|
||||||
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('take(): count must be >= 0, got -1');
|
||||||
|
|
||||||
|
c\take(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSkipRejectsNegativeCount()
|
||||||
|
{
|
||||||
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('skip(): count must be >= 0, got -1');
|
||||||
|
|
||||||
|
c\skip(-1);
|
||||||
|
}
|
||||||
|
|
||||||
// prepend / append / concat / merge
|
// prepend / append / concat / merge
|
||||||
|
|
||||||
public function testPrepend()
|
public function testPrepend()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user