Skip to content

Commit

Permalink
Add pipe(), compose()
Browse files Browse the repository at this point in the history
  • Loading branch information
mpetrovich committed Nov 3, 2020
1 parent c1110c0 commit 3b55c02
Show file tree
Hide file tree
Showing 6 changed files with 365 additions and 0 deletions.
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"src/call.php",
"src/chain.php",
"src/compare.php",
"src/compose.php",
"src/contains.php",
"src/currify.php",
"src/currifyN.php",
Expand Down Expand Up @@ -94,6 +95,7 @@
"src/partial.php",
"src/partialRight.php",
"src/pick.php",
"src/pipe.php",
"src/pluck.php",
"src/property.php",
"src/reduce.php",
Expand Down
106 changes: 106 additions & 0 deletions docs/Operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Operation | Signature | Curried
[call](#call) | `call(callable $callable /*, ...args */): mixed` |
[chain](#chain) | `chain($input = null): Dash\Dash` | `Curry\chain`
[compare](#compare) | `compare($a, $b): integer` | `Curry\compare`
[compose](#compose) | `compose(callable ...$fns): callable` |
[contains](#contains--includes) / includes | `contains($iterable, $target, $comparator = 'Dash\equal'): boolean` | `Curry\contains`
[currify](#currify) | `currify(callable $callable, array $args = [], $rotate = 1): function\|mixed` |
[currifyN](#currifyn) | `currifyN(callable $callable, $totalArgs, array $args = [], $rotate = 1): function\|mixed` |
Expand Down Expand Up @@ -65,6 +66,7 @@ Operation | Signature | Curried
[partial](#partial) | `partial($callable /*, ...args */): callable` |
[partialRight](#partialright) | `partialRight($callable /*, ...args */): callable` |
[pick](#pick) | `pick($iterable, $keys): array` | `Curry\pick`
[pipe](#pipe) | `pipe(callable ...$fns): callable` |
[pluck](#pluck) | `pluck($iterable, $path, $default = null): array` | `Curry\pluck`
[property](#property) | `property($path, $default = null): function` | `Curry\property`
[reduce](#reduce) | `reduce($iterable, $iteratee, $initial = []): mixed` | `Curry\reduce`
Expand Down Expand Up @@ -456,6 +458,58 @@ Dash\compare(2, 2);

[↑ Top](#operations)

compose
---
See also: `pipe()`

```php
compose(callable ...$fns): callable
```
Returns a new function that performs right-to-left function composition.

The last function can have any arity, but the rest must be unary.


Parameter | Type | Description
--- | --- | :---
`...$fns` | `callable` |
**Returns** | `callable` | New function that composes `$fns` right-to-left

**Example:**
```php
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};
$square = function ($v) {
return $v * $v;
};

$composed = Dash\compose($square, $triple, $addOne);
$composed(1); // === 36

```

**Example:** Last function can accept multiple arguments
```php
$pow = function ($base, $exp) {
return pow($base, $exp);
};
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};

$composed = Dash\compose($triple, $addOne, $pow);
$composed(2, 3); // === 27
```

[↑ Top](#operations)

contains / includes
---

Expand Down Expand Up @@ -2649,6 +2703,58 @@ Dash\pick(['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4], ['b', 'c']);

[↑ Top](#operations)

pipe
---
See also: `compose()`

```php
pipe(callable ...$fns): callable
```
Returns a new function that performs left-to-right function composition.

The first function can have any arity, but the rest must be unary.


Parameter | Type | Description
--- | --- | :---
`...$fns` | `callable` |
**Returns** | `callable` | New function that composes `$fns` left-to-right

**Example:**
```php
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};
$square = function ($v) {
return $v * $v;
};

$piped = Dash\pipe($addOne, $triple, $square);
$piped(1); // === 36

```

**Example:** First function can accept multiple arguments
```php
$pow = function ($base, $exp) {
return pow($base, $exp);
};
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};

$piped = Dash\pipe($pow, $addOne, $triple);
$piped(2, 3); // === 27
```

[↑ Top](#operations)

pluck
---
See also: `map()`
Expand Down
57 changes: 57 additions & 0 deletions src/compose.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Dash;

/**
* Returns a new function that performs right-to-left function composition.
*
* The last function can have any arity, but the rest must be unary.
*
* @see pipe()
*
* @param callable ...$fns
* @return callable New function that composes `$fns` right-to-left
*
* @example
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};
$square = function ($v) {
return $v * $v;
};
$composed = Dash\compose($square, $triple, $addOne);
$composed(1); // === 36
*
* @example Last function can accept multiple arguments
$pow = function ($base, $exp) {
return pow($base, $exp);
};
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};
$composed = Dash\compose($triple, $addOne, $pow);
$composed(2, 3); // === 27
*/
function compose(callable ...$fns)
{
return function (...$args) use ($fns) {
$fns = array_reverse($fns);
$first = first($fns);
$rest = array_slice($fns, 1);

$result = call_user_func($first, ...$args);
foreach ($rest as $fn) {
$result = call_user_func($fn, $result);
}

return $result;
};
}
56 changes: 56 additions & 0 deletions src/pipe.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace Dash;

/**
* Returns a new function that performs left-to-right function composition.
*
* The first function can have any arity, but the rest must be unary.
*
* @see compose()
*
* @param callable ...$fns
* @return callable New function that composes `$fns` left-to-right
*
* @example
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};
$square = function ($v) {
return $v * $v;
};
$piped = Dash\pipe($addOne, $triple, $square);
$piped(1); // === 36
*
* @example First function can accept multiple arguments
$pow = function ($base, $exp) {
return pow($base, $exp);
};
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};
$piped = Dash\pipe($pow, $addOne, $triple);
$piped(2, 3); // === 27
*/
function pipe(callable ...$fns)
{
return function (...$args) use ($fns) {
$first = first($fns);
$rest = array_slice($fns, 1);

$result = call_user_func($first, ...$args);
foreach ($rest as $fn) {
$result = call_user_func($fn, $result);
}

return $result;
};
}
72 changes: 72 additions & 0 deletions tests/composeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

/**
* @covers Dash\compose
*/
class composeTest extends PHPUnit_Framework_TestCase
{
public function testCanComposeOneUnaryFunction()
{
$addOne = function ($v) {
return $v + 1;
};
$composed = Dash\compose($addOne);

$this->assertSame(2, $composed(1));
}

public function testCanComposeOneNonUnaryFunction()
{
$pow = function ($base, $exp) {
return pow($base, $exp);
};
$composed = Dash\compose($pow);

$this->assertSame(8, $composed(2, 3));
}

public function testCanComposeTwoFunctions()
{
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};
$composed = Dash\compose($triple, $addOne);

$this->assertSame(6, $composed(1));
}

public function testCanComposeMoreThanTwoFunctions()
{
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};
$square = function ($v) {
return $v * $v;
};
$composed = Dash\compose($square, $triple, $addOne);

$this->assertSame(36, $composed(1));
}

public function testFirstFunctionCanBeNonUnary()
{
$pow = function ($base, $exp) {
return pow($base, $exp);
};
$addOne = function ($v) {
return $v + 1;
};
$triple = function ($v) {
return $v * 3;
};
$composed = Dash\compose($triple, $addOne, $pow);

$this->assertSame(27, $composed(2, 3));
}
}

0 comments on commit 3b55c02

Please sign in to comment.