diff --git a/composer.json b/composer.json index 11f675f..4af424b 100644 --- a/composer.json +++ b/composer.json @@ -41,6 +41,7 @@ "src/reduce.php", "src/take.php", "src/flatten.php", + "src/each.php", "src/until.php" ] }, diff --git a/src/Transducer/Each.php b/src/Transducer/Each.php new file mode 100644 index 0000000..f0fe2d9 --- /dev/null +++ b/src/Transducer/Each.php @@ -0,0 +1,51 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace LazyLists\Transducer; + +class Each extends PureTransducer implements TransducerInterface +{ + /** + * Applies $sideEffect to each $item, but does not change the $item itself + * + * @var callable + */ + protected $sideEffect; + + public function __construct(callable $sideEffect) + { + $this->sideEffect = $sideEffect; + } + + public function computeNextResult($item) + { + $sideEffect = $this->sideEffect; + $sideEffect($item); + $this->iterator->yieldToNextTransducer($item); + } + + public function getEmptyFinalResult() + { + return []; + } + + public function computeFinalResult($previousResult, $lastValue) + { + if (\is_null($previousResult)) { + return []; + } + $previousResult[] = $lastValue; + return $previousResult; + } +} diff --git a/src/each.php b/src/each.php new file mode 100644 index 0000000..ce7630d --- /dev/null +++ b/src/each.php @@ -0,0 +1,38 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace LazyLists; + +use LazyLists\Exception\InvalidArgumentException; + +/** + * Calls `$sideEffect` on each element in `$list`. + * If $list is omitted, returns a Transducer to be used with `pipe()` instead. + * + * @param callable $sideEffect + * @param array|\Traversable|null $list + * @see \LazyLists\Transducer\Map + * @return mixed void or \LazyLists\Transducer\Map + */ +function each(callable $sideEffect, $list = null) +{ + if (\is_null($list)) { + return new \LazyLists\Transducer\Each($sideEffect); + } + + InvalidArgumentException::assertCollection($list, __FUNCTION__, 2); + foreach ($list as $key => $item) { + $sideEffect($item, $key); + } +} diff --git a/tests/EachTest.php b/tests/EachTest.php new file mode 100644 index 0000000..ab2fbd4 --- /dev/null +++ b/tests/EachTest.php @@ -0,0 +1,36 @@ +assertEquals(2, $c); + } + + public function testPassNoCollection() + { + $this->expectException(\Exception::class); + each(function () { + return; + }, 'invalidCollection'); + } + + public function testPassNonCallable() + { + $this->expectException(\TypeError::class); + each('notACallable', []); + } +} diff --git a/tests/PipeTest.php b/tests/PipeTest.php index 6ee8df5..42aa1b5 100644 --- a/tests/PipeTest.php +++ b/tests/PipeTest.php @@ -12,6 +12,8 @@ use function LazyLists\flatten; use function LazyLists\reduce; use function LazyLists\take; +use function LazyLists\each; +use function LazyLists\until; /** * "integration" tests @@ -195,4 +197,23 @@ public function testRealUseCase() $this->assertEquals(7, $sup_count); $this->assertEquals(3, $sum_count); } + + public function testFlattenEachUntil() + { + $list = [ + [1, 2], + [3, 4] + ]; + $c = 0; + $pipe = pipe( + flatten(1), + each(function ($v) use (&$c) { + $c = $c + $v; + }), + until(function ($v) use (&$c) { + return $c > 6; + }) + ); + $this->assertSame([1, 2, 3], $pipe($list)); + } } diff --git a/tests/Transducer/EachTest.php b/tests/Transducer/EachTest.php new file mode 100644 index 0000000..d2ebfbe --- /dev/null +++ b/tests/Transducer/EachTest.php @@ -0,0 +1,24 @@ +assertSame([1, 2, 3], $pipe2([1, 2, 3])); + } +}