Skip to content

Commit

Permalink
Merge pull request #5 from lstrojny/feature/partial_right
Browse files Browse the repository at this point in the history
Implement bind_right()
  • Loading branch information
igorw committed Dec 12, 2014
2 parents c5593b8 + 78f7c8c commit 36c9635
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 26 deletions.
19 changes: 18 additions & 1 deletion README.md
Expand Up @@ -111,10 +111,27 @@ $add = function ($a, $b) {

$addOne = Partial\bind($add, 1);

echo sprintf("%s\n", $addOne(5));
echo sprintf("%d\n", $addOne(5));
// outputs 6
```

### bind_right

```php
<?php

use React\Partial;

$div = function ($a, $b, $c) {
return $a / $b / $c;
};

$addOne = Partial\bind_right($add, 20, 10);

echo sprintf("%F\n", $addOne(100)); // 100 / 20 / 10
// outputs 0.5
```

### placeholder

It is possible to use the `` function (there is an alias called
Expand Down
8 changes: 5 additions & 3 deletions src/React/Partial/Util.php
Expand Up @@ -6,9 +6,11 @@ final class Util
{
public static function bind(/*$fn, $args...*/)
{
$args = func_get_args();
$fn = array_shift($args);

return call_user_func_array('React\Partial\bind', func_get_args());
}

public static function bindRight(/*$fn, $args...*/)
{
return call_user_func_array('React\Partial\bind_right', func_get_args());
}
}
44 changes: 30 additions & 14 deletions src/React/Partial/functions.php
Expand Up @@ -2,42 +2,58 @@

namespace React\Partial;

use React\Partial\Placeholder;

function bind(/*$fn, $args...*/)
{
$args = func_get_args();
$fn = array_shift($args);

return function () use ($fn, $args) {
return call_user_func_array($fn, mergeParameters($args, func_get_args()));
return call_user_func_array($fn, mergeLeft($args, func_get_args()));
};
}

function bind_right(/*$fn, $args...*/)
{
$args = func_get_args();
$fn = array_shift($args);

return function () use ($fn, $args) {
return call_user_func_array($fn, mergeRight($args, func_get_args()));
};
}

/**
* @return Partial
*/
/** @return Placeholder */
function …()
{
return Placeholder::create();
}

/**
* @return Partial
*/
/** @return Placeholder */
function placeholder()
{
return …();
}

/** @internal */
function mergeParameters(array $left, array $right)
function mergeLeft(array $left, array $right)
{
resolvePlaceholder($left, $right);
return array_merge($left, $right);
}

/** @internal */
function mergeRight(array $left, array $right)
{
resolvePlaceholder($left, $right);
return array_merge($right, $left);
}

/** @internal */
function resolvePlaceholder(array &$parameters, array &$source)
{
foreach ($left as $position => &$param) {
foreach ($parameters as $position => &$param) {
if ($param instanceof Placeholder) {
$param = $param->resolve($right, $position);
$param = $param->resolve($source, $position);
}
}

return array_merge($left, $right);
}
81 changes: 81 additions & 0 deletions tests/React/Partial/BindRightTest.php
@@ -0,0 +1,81 @@
<?php

namespace React\Partial;

class BindRightTest extends \PHPUnit_Framework_TestCase
{
public function testBindWithNoArgs()
{
$div = $this->createDivFunction();
$newDiv = bind_right($div);
$this->assertSame(2, $newDiv(4, 2));
}

public function testBindWithOneArg()
{
$div = $this->createDivFunction();
$divOne = bind_right($div, 4);
$this->assertSame(0.5, $divOne(2));
}

public function testBindWithTwoArgs()
{
$div = $this->createDivFunction();
$divTwo = bind_right($div, 2, 4);
$this->assertSame(0.5, $divTwo());
}

public function testBindWithPlaceholder()
{
$div = $this->createDivFunction();
$divFun = bind_right($div, …(), 4);
$this->assertSame(5, $divFun(20));
$this->assertSame(10, $divFun(40));
}

public function testBindWithMultiplePlaceholders()
{
$div = $this->createDivFunction();
$divTwo = bind_right($div, …(), 2, …());
$this->assertSame(1, $divTwo(4, 2));
$this->assertSame(1, $divTwo(10, 5));
$this->assertSame(25, $divTwo(100, 2));
}

public function testPlaceholderParameterPosition()
{
$substr = bind_right('substr', …(), 0, …());
$this->assertSame('foo', $substr('foo', 3));
$this->assertSame('fo', $substr('foo', 2));
$this->assertSame('f', $substr('foo', 1));
}

/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Cannot resolve parameter placeholder at position 0. Parameter stack is empty
*/
public function testStringConversion()
{
$div = $this->createDivFunction();
$divTwo = bind_right($div, …(), 2);

$divTwo();
}

public function testAliasForUnicodePlaceholderFunction()
{
$this->assertSame(…(), placeholder());
}

private function createDivFunction()
{
return function () {
$args = func_get_args();
$value = array_shift($args);
foreach ($args as $arg) {
$value /= $arg;
}
return $value;
};
}
}
1 change: 0 additions & 1 deletion tests/React/Partial/BindTest.php
Expand Up @@ -25,7 +25,6 @@ public function testBindWithTwoArgs()
$this->assertSame(6, $addOneAndFive());
}


public function testBindWithPlaceholder()
{
$add = $this->createAddFunction();
Expand Down
21 changes: 14 additions & 7 deletions tests/React/Partial/UtilTest.php
Expand Up @@ -6,17 +6,24 @@

class UtilTest extends \PHPUnit_Framework_TestCase
{
public function testBindWithTwoArgs()
public function testBind()
{
$add = $this->createAddFunction();
$addOneAndFive = Partial::bind($add, 1, 5);
$this->assertSame(6, $addOneAndFive());
$div = $this->createDivFunction();
$divFun = Partial::bind($div, 10, 5);
$this->assertSame(0.02, $divFun(100));
}

private function createAddFunction()
public function testBindRight()
{
return function ($a, $b) {
return $a + $b;
$div = $this->createDivFunction();
$divFun = Partial::bindRight($div, 10, 5);
$this->assertSame(2, $divFun(100));
}

private function createDivFunction()
{
return function ($a, $b, $c) {
return $a / $b / $c;
};
}
}

0 comments on commit 36c9635

Please sign in to comment.