Permalink
Browse files

Implement bind_right()

  • Loading branch information...
1 parent 04ef40e commit 78f7c8c37a4f35996e909ab7fb11a0507591c20d @lstrojny lstrojny committed Nov 22, 2014
View
@@ -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
@@ -6,9 +6,11 @@
{
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());
+ }
}
@@ -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);
}
@@ -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;
+ };
+ }
+}
@@ -25,7 +25,6 @@ public function testBindWithTwoArgs()
$this->assertSame(6, $addOneAndFive());
}
-
public function testBindWithPlaceholder()
{
$add = $this->createAddFunction();
@@ -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 78f7c8c

Please sign in to comment.