Skip to content

Commit 63aaefd

Browse files
authored
Add juxt for applying multiple functions to the same arguments (#263)
1 parent c9d87fb commit 63aaefd

5 files changed

Lines changed: 123 additions & 0 deletions

File tree

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
"src/Functional/InvokeIf.php",
7575
"src/Functional/InvokeLast.php",
7676
"src/Functional/Invoker.php",
77+
"src/Functional/Juxt.php",
7778
"src/Functional/Last.php",
7879
"src/Functional/LastIndexOf.php",
7980
"src/Functional/LessThan.php",

docs/functional-php.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,23 @@ use function Functional\partial_method;
329329
$registeredUsers = select($users, partial_method('isRegistered'));
330330
```
331331

332+
## juxt()
333+
Takes a list of functions and returns a new function that applies each function to the given arguments and returns an array of the results. Inspired by Clojure's `juxt`.
334+
335+
``callable Functional\juxt(callable ...$functions)``
336+
337+
```php
338+
use function Functional\juxt;
339+
340+
$getStats = juxt('min', 'max');
341+
$getStats(3, 1, 5, 2); // [1, 5]
342+
343+
$transform = juxt('strtoupper', 'strtolower', 'strrev');
344+
$transform('Hello'); // ['HELLO', 'hello', 'olleH']
345+
```
346+
347+
_See also `converge()`, which additionally passes the results through a converging function._
348+
332349
## converge()
333350

334351
``callable Functional\converge(callable $convergingFunction, callable[] branchingFunctions)``

src/Functional/Functional.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ final class Functional
237237
*/
238238
const invoker = '\Functional\invoker';
239239

240+
/**
241+
* @see \Functional\juxt
242+
*/
243+
const juxt = '\Functional\juxt';
244+
240245
/**
241246
* @see \Functional\last
242247
*/

src/Functional/Juxt.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/**
4+
* @package Functional-php
5+
* @author Lars Strojny <lstrojny@php.net>
6+
* @copyright 2011-2021 Lars Strojny
7+
* @license https://opensource.org/licenses/MIT MIT
8+
* @link https://github.com/lstrojny/functional-php
9+
*/
10+
11+
namespace Functional;
12+
13+
/**
14+
* Takes a list of functions and returns a new function that applies each
15+
* function to the given arguments and returns an array of the results.
16+
*
17+
* @param callable ...$functions
18+
* @return callable
19+
* @no-named-arguments
20+
*/
21+
function juxt(callable ...$functions)
22+
{
23+
return function (...$values) use ($functions) {
24+
$result = [];
25+
26+
foreach ($functions as $function) {
27+
$result[] = $function(...$values);
28+
}
29+
30+
return $result;
31+
};
32+
}

tests/Functional/JuxtTest.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
/**
4+
* @package Functional-php
5+
* @author Lars Strojny <lstrojny@php.net>
6+
* @copyright 2011-2021 Lars Strojny
7+
* @license https://opensource.org/licenses/MIT MIT
8+
* @link https://github.com/lstrojny/functional-php
9+
*/
10+
11+
namespace Functional\Tests;
12+
13+
use function Functional\juxt;
14+
15+
class JuxtTest extends AbstractTestCase
16+
{
17+
public function test(): void
18+
{
19+
$juxted = juxt('strtoupper', 'strtolower', 'strrev');
20+
21+
self::assertSame(['HELLO', 'hello', 'olleH'], $juxted('Hello'));
22+
}
23+
24+
public function testWithMultipleArguments(): void
25+
{
26+
$minMax = juxt('min', 'max');
27+
28+
self::assertSame([1, 5], $minMax(3, 1, 5, 2));
29+
}
30+
31+
public function testWithArrayFunctions(): void
32+
{
33+
$stats = juxt('array_sum', 'count');
34+
35+
self::assertSame([15, 5], $stats([1, 2, 3, 4, 5]));
36+
}
37+
38+
public function testWithClosures(): void
39+
{
40+
$double = static function ($x) {
41+
return $x * 2;
42+
};
43+
$square = static function ($x) {
44+
return $x * $x;
45+
};
46+
$negate = static function ($x) {
47+
return -$x;
48+
};
49+
50+
$juxted = juxt($double, $square, $negate);
51+
52+
self::assertSame([10, 25, -5], $juxted(5));
53+
}
54+
55+
public function testWithNoFunctions(): void
56+
{
57+
$juxted = juxt();
58+
59+
self::assertSame([], $juxted('anything'));
60+
}
61+
62+
public function testWithSingleFunction(): void
63+
{
64+
$juxted = juxt('strlen');
65+
66+
self::assertSame([5], $juxted('hello'));
67+
}
68+
}

0 commit comments

Comments
 (0)