Skip to content

Commit

Permalink
feat: Add scanLeft operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Sep 21, 2020
1 parent 18b9b1d commit ff0c7e4
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 0 deletions.
25 changes: 25 additions & 0 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,30 @@ Signature: ``Collection::scale(float $lowerBound, float $upperBound, ?float $wan
$collection = Collection::range(0, 10, 2)
->scale(0, 10, 5, 15, 3);
scanLeft
~~~~~~~~

Takes the initial value and the first item of the list and applies the function to them, then feeds the function with
this result and the second argument and so on. It returns the list of intermediate and final results.

Interface: `ScanLeftable`_

Signature: ``Collection::scanLeft(callable $callback, $initial = null);``

.. code-block:: php
$callback = static function ($carry, $value) {
return $carry / $value;
};
Collection::fromIterable([4, 2, 4])
->scanLeft($callback, 64)
->normalize(); // [64 ,16 ,8 ,2]
Collection::empty()
->scanLeft($callback, 3)
->normalize(); // [3]
since
~~~~~

Expand Down Expand Up @@ -1756,6 +1780,7 @@ Signature: ``Collection::zip(iterable ...$iterables);``
.. _Reductionable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Reductionable.php
.. _Reverseable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Reverseable.php
.. _Scaleable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Scaleable.php
.. _ScanLeftable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/ScanLeftable.php
.. _Sinceable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Sinceable.php
.. _Sliceable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Sliceable.php
.. _Sortable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Sortable.php
Expand Down
25 changes: 25 additions & 0 deletions spec/loophp/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,31 @@ public function it_can_scale(): void
->shouldIterateAs([5.0, 8.01, 11.02, 12.78, 14.03, 15.0]);
}

public function it_can_scanleft(): void
{
$callback = static function ($carry, $value) {
return $carry / $value;
};

$result = static function () {
yield 0 => 64;

yield 0 => 16;

yield 1 => 8;

yield 2 => 2;
};

$this::fromIterable([4, 2, 4])
->scanLeft($callback, 64)
->shouldIterateAs($result());

$this::fromIterable([])
->scanLeft($callback, 3)
->shouldIterateAs([3]);
}

public function it_can_shuffle(): void
{
$data = range('A', 'Z');
Expand Down
6 changes: 6 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
use loophp\collection\Operation\RSample;
use loophp\collection\Operation\Run;
use loophp\collection\Operation\Scale;
use loophp\collection\Operation\ScanLeft;
use loophp\collection\Operation\Shuffle;
use loophp\collection\Operation\Since;
use loophp\collection\Operation\Slice;
Expand Down Expand Up @@ -676,6 +677,11 @@ public function scale(
return $this->run(Scale::of()($lowerBound)($upperBound)($wantedLowerBound)($wantedUpperBound)($base));
}

public function scanLeft(callable $callback, $initial = null): CollectionInterface
{
return $this->run(ScanLeft::of()($callback)($initial));
}

public function shuffle(): CollectionInterface
{
return $this->run(Shuffle::of());
Expand Down
3 changes: 3 additions & 0 deletions src/Contract/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
use loophp\collection\Contract\Operation\Reverseable;
use loophp\collection\Contract\Operation\RSampleable;
use loophp\collection\Contract\Operation\Scaleable;
use loophp\collection\Contract\Operation\ScanLeftable;
use loophp\collection\Contract\Operation\Shuffleable;
use loophp\collection\Contract\Operation\Sinceable;
use loophp\collection\Contract\Operation\Sliceable;
Expand Down Expand Up @@ -158,6 +159,7 @@
* @template-extends Reverseable<TKey, T>
* @template-extends RSampleable<TKey, T>
* @template-extends Scaleable<TKey, T>
* @template-extends ScanLeftable<TKey, T>
* @template-extends Shuffleable<TKey, T>
* @template-extends Sinceable<TKey, T>
* @template-extends Sliceable<TKey, T>
Expand Down Expand Up @@ -245,6 +247,7 @@ interface Collection extends
Reverseable,
RSampleable,
Scaleable,
ScanLeftable,
Shuffleable,
Sinceable,
Sliceable,
Expand Down
23 changes: 23 additions & 0 deletions src/Contract/Operation/ScanLeftable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Contract\Operation;

use loophp\collection\Contract\Collection;

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*/
interface ScanLeftable
{
/**
* @param mixed $initial
* @psalm-param T|null $initial
*
* @psalm-return \loophp\collection\Contract\Collection<TKey, T>
*/
public function scanLeft(callable $callback, $initial = null): Collection;
}
54 changes: 54 additions & 0 deletions src/Operation/ScanLeft.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

use Closure;
use Generator;
use Iterator;

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*
* phpcs:disable Generic.Files.LineLength.TooLong
*/
final class ScanLeft extends AbstractOperation
{
/**
* @psalm-return Closure(callable(T|null, T, TKey, Iterator<TKey, T>):(T|null)): Closure(T|null): Closure(Iterator<TKey, T>): Generator<int|TKey, T|null>
*/
public function __invoke(): Closure
{
return
/**
* @psalm-param callable(T|null, T, TKey, Iterator<TKey, T>):(T|null) $callback
*
* @psalm-return Closure(T|null): Closure(Iterator<TKey, T>): Generator<int|TKey, T|null>
*/
static function (callable $callback): Closure {
return
/**
* @param mixed|null $initial
* @psalm-param T|null $initial
*
* @psalm-return Closure(Iterator<TKey, T>): Generator<int|TKey, T|null>
*/
static function ($initial = null) use ($callback): Closure {
return
/**
* @psalm-param Iterator<TKey, T> $iterator
*
* @psalm-return Generator<int|TKey, T|null>
*/
static function (Iterator $iterator) use ($callback, $initial): Generator {
yield $initial;

return yield from Reduction::of()($callback)($initial)($iterator);
};
};
};
}
}

0 comments on commit ff0c7e4

Please sign in to comment.