Skip to content

Commit

Permalink
Make default callback the identity function. (#214)
Browse files Browse the repository at this point in the history
* Make default callback the identity function.

This commit changes the `select`, `reject`, `some`, `none`, and `every`
functions so that the default callback argument is the `id` function.

* Provide more clarity in docs when $callback is id().
  • Loading branch information
jasonmm authored Mar 29, 2020
1 parent a736d25 commit e495a97
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 14 deletions.
15 changes: 11 additions & 4 deletions docs/functional-php.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ map(range(0, 100), function($v) {return $v + 1;});

## every() & invoke()

``Functional\every(array|Traversable $collection, callable $callback)``
``Functional\every(array|Traversable $collection, callable $callback = null)``

```php
<?php
Expand All @@ -107,10 +107,11 @@ if (every($users, function($user, $collectionKey, $collection) {return $user->is
}
```

If `$callback` is not provided then the `id()` function is used and `every` will return true if every value in the collection is truthy.

## some()

``bool Functional\some(array|Traversable $collection, callable $callback)``
``bool Functional\some(array|Traversable $collection, callable $callback = null)``

```php
<?php
Expand All @@ -121,6 +122,7 @@ if (some($users, function($user, $collectionKey, $collection) use($me) {return $
}
```

If `$callback` is not provided then the `id()` function is used and `some` will return true if at least one value in the collection is truthy.

## none()

Expand All @@ -135,12 +137,13 @@ if (none($users, function($user, $collectionKey, $collection) {return $user->isA
}
```

If `$callback` is not provided then the `id()` function is used and `none` will return true if every value in the collection is falsey.

## reject() & select()

``array Functional\select(array|Traversable $collection, callable $callback)``
``array Functional\select(array|Traversable $collection, callable $callback = null)``

``array Functional\reject(array|Traversable $collection, callable $callback)``
``array Functional\reject(array|Traversable $collection, callable $callback = null)``

```php
<?php
Expand All @@ -154,6 +157,10 @@ $activeUsers = select($users, $fn);
$inactiveUsers = reject($users, $fn);
```

For both functions array keys are preserved.

For both functions if a value for $callback is not provided then the `id()` function is used. For `select`, this means that only the truthy values in the collection will be returned. For `reject`, this means that only the falsey values in the collection will be returned.

Alias for `Functional\select()` is `Functional\filter()`

**Note:** This may unexpectedly turn your indexed array into an associative array, [see here](https://github.com/lstrojny/functional-php/issues/39#issuecomment-48034617) if you always want to keep an indexed array.
Expand Down
8 changes: 6 additions & 2 deletions src/Functional/Every.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@
* Callback arguments will be element, index, collection
*
* @param Traversable|array $collection
* @param callable $callback
* @param callable|null $callback
* @return bool
*/
function every($collection, callable $callback)
function every($collection, callable $callback = null)
{
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);

if ($callback === null) {
$callback = '\Functional\id';
}

foreach ($collection as $index => $element) {
if (!$callback($element, $index, $collection)) {
return false;
Expand Down
8 changes: 6 additions & 2 deletions src/Functional/None.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@
* Callback arguments will be element, index, collection.
*
* @param Traversable|array $collection
* @param callable $callback
* @param callable|null $callback
* @return bool
*/
function none($collection, callable $callback)
function none($collection, callable $callback = null)
{
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);

if ($callback === null) {
$callback = '\Functional\id';
}

foreach ($collection as $index => $element) {
if ($callback($element, $index, $collection)) {
return false;
Expand Down
8 changes: 6 additions & 2 deletions src/Functional/Reject.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@
* Functional\select(). Callback arguments will be element, index, collection
*
* @param Traversable|array $collection
* @param callable $callback
* @param callable|null $callback
* @return array
*/
function reject($collection, callable $callback)
function reject($collection, callable $callback = null)
{
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);

$aggregation = [];

if ($callback === null) {
$callback = '\Functional\id';
}

foreach ($collection as $index => $element) {
if (!$callback($element, $index, $collection)) {
$aggregation[$index] = $element;
Expand Down
8 changes: 6 additions & 2 deletions src/Functional/Select.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@
* Opposite is Functional\reject(). Callback arguments will be element, index, collection
*
* @param Traversable|array $collection
* @param callable $callback
* @param callable|null $callback
* @return array
*/
function select($collection, callable $callback)
function select($collection, callable $callback = null)
{
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);

$aggregation = [];

if ($callback === null) {
$callback = '\Functional\id';
}

foreach ($collection as $index => $element) {
if ($callback($element, $index, $collection)) {
$aggregation[$index] = $element;
Expand Down
8 changes: 6 additions & 2 deletions src/Functional/Some.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@
* traversing the collection if a truthy element is found. Callback arguments will be value, index, collection
*
* @param Traversable|array $collection
* @param callable $callback
* @param callable|null $callback
* @return bool
*/
function some($collection, callable $callback)
function some($collection, callable $callback = null)
{
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);

if ($callback === null) {
$callback = '\Functional\id';
}

foreach ($collection as $index => $element) {
if ($callback($element, $index, $collection)) {
return true;
Expand Down
8 changes: 8 additions & 0 deletions tests/Functional/EveryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ public function testPassNoCollection()
every('invalidCollection', 'strlen');
}

public function testPassNoCallable()
{
$this->assertTrue(every($this->goodArray));
$this->assertTrue(every($this->goodIterator));
$this->assertTrue(every($this->badArray));
$this->assertTrue(every($this->badIterator));
}

public function testExceptionIsThrownInArray()
{
$this->expectException('DomainException');
Expand Down
8 changes: 8 additions & 0 deletions tests/Functional/NoneTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ public function testPassNonCallable()
none($this->goodArray, 'undefinedFunction');
}

public function testPassNoCallable()
{
$this->assertFalse(none($this->goodArray));
$this->assertFalse(none($this->goodIterator));
$this->assertFalse(none($this->badArray));
$this->assertFalse(none($this->badIterator));
}

public function testExceptionIsThrownInArray()
{
$this->expectException('DomainException');
Expand Down
9 changes: 9 additions & 0 deletions tests/Functional/RejectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ public function testPassNonCallable()
reject($this->list, 'undefinedFunction');
}

public function testPassNoCallable()
{
$this->assertSame([], reject($this->list));
$this->assertSame([], reject($this->listIterator));
$this->assertSame([], reject($this->hash));
$this->assertSame([], reject($this->hashIterator));
$this->assertSame([1 => false], reject([true, false, true]));
}

public function testPassNoCollection()
{
$this->expectArgumentError('Functional\reject() expects parameter 1 to be array or instance of Traversable');
Expand Down
9 changes: 9 additions & 0 deletions tests/Functional/SelectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ public function testPassNonCallable($functionName)
$functionName($this->list, 'undefinedFunction');
}

public function testPassNoCallable()
{
$this->assertSame(['value', 'wrong', 'value'], select($this->list));
$this->assertSame(['value', 'wrong', 'value'], select($this->listIterator));
$this->assertSame(['k1' => 'value', 'k2' => 'wrong', 'k3' => 'value'], select($this->hash));
$this->assertSame(['k1' => 'value', 'k2' => 'wrong', 'k3' => 'value'], select($this->hashIterator));
$this->assertSame([0 => true, 2 => true], select([true, false, true]));
}

/**
* @dataProvider getAliases
*/
Expand Down
8 changes: 8 additions & 0 deletions tests/Functional/SomeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ public function testPassNonCallable()
some($this->goodArray, 'undefinedFunction');
}

public function testPassNoCallable()
{
$this->assertTrue(some($this->goodArray));
$this->assertTrue(some($this->goodIterator));
$this->assertTrue(some($this->badArray));
$this->assertTrue(some($this->badIterator));
}

public function testPassNoCollection()
{
$this->expectArgumentError('Functional\some() expects parameter 1 to be array or instance of Traversable');
Expand Down

0 comments on commit e495a97

Please sign in to comment.