Skip to content

Commit 939aeed

Browse files
author
Roman Lakhtadyr
authored
Merge pull request #8 from nerd-components/functional
add tail recursion
2 parents d9a777e + d0d0194 commit 939aeed

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"files": [
99
"src/Nerd/Common/Arrays.php",
1010
"src/Nerd/Common/Classes.php",
11-
"src/Nerd/Common/Strings.php"
11+
"src/Nerd/Common/Strings.php",
12+
"src/Nerd/Common/Functional.php"
1213
]
1314
},
1415
"require-dev": {

src/Nerd/Common/Functional.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Nerd\Common\Functional;
4+
5+
/**
6+
* Optimize given function for tail recursion.
7+
*
8+
* @param callable $fn
9+
* @return \Closure
10+
*/
11+
function tail(callable $fn)
12+
{
13+
$underCall = false;
14+
$pool = [];
15+
return function (...$args) use (&$fn, &$underCall, &$pool) {
16+
$result = null;
17+
$pool[] = $args;
18+
if (!$underCall) {
19+
$underCall = true;
20+
while ($pool) {
21+
$head = array_shift($pool);
22+
$result = $fn(...$head);
23+
}
24+
$underCall = false;
25+
}
26+
return $result;
27+
};
28+
}

tests/FunctionalTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace tests;
4+
5+
use function Nerd\Common\Functional\tail;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class FunctionalTest extends TestCase
9+
{
10+
public function testTailRecursion()
11+
{
12+
$func = tail(function ($max, $acc = 0) use (&$func) {
13+
if ($max == $acc) {
14+
return $acc;
15+
}
16+
return $func($max, $acc + 1);
17+
});
18+
$this->assertEquals(10000, $func(10000));
19+
}
20+
}

0 commit comments

Comments
 (0)