Skip to content

Instantly share code, notes, and snippets.

@ThomasWeinert
Forked from beberlei/tailrecursion.php
Created November 28, 2012 18:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ThomasWeinert/4162905 to your computer and use it in GitHub Desktop.
Save ThomasWeinert/4162905 to your computer and use it in GitHub Desktop.
PHP Tail Recursion
<?php
class TailRecursion {
private $_function = NULL;
private $_arguments = array();
private $_recursing = FALSE;
private $_recursion = NULL;
public function __construct(Callable $function) {
$this->_function = $function;
}
public function recursion() {
return call_user_func_array($this->_recursion, func_get_args());
}
public function __invoke() {
$this->prepare();
return call_user_func_array($this->_recursion, func_get_args());
}
private function prepare() {
if (NULL === $this->_recursion) {
$this->_arguments = array();
$this->_recursing = FALSE;
$function = $this->_function->bindTo($this);
$this->_recursion = function() use ($function) {
$this->_arguments[] = func_get_args();
if (!$this->_recursing) {
$this->_recursing = TRUE;
while ($this->_arguments) {
$result = call_user_func_array($function, array_shift($this->_arguments));
}
$this->_recursing = FALSE;
return $result;
}
};
}
}
}
$facOne = new TailRecursion(
function ($n, $acc = 1) {
if ($n == 1) {
return $acc;
}
return $this->recursion($n - 1, $acc * $n);
}
);
var_dump($facOne(4));
/**
* possible, but useful?
*/
class NestedRecursion {
private $_function = NULL;
public function __construct(Callable $function) {
$this->_function = $function;
}
public function __invoke() {
return call_user_func_array(array($this, 'recursion'), func_get_args());
}
public function recursion() {
$function = $this->_function->bindTo($this);
return call_user_func_array($function, func_get_args());
}
}
$facTwo = new NestedRecursion(
function ($n, $acc = 1) {
if ($n == 1) {
return $acc;
}
return $this->recursion($n - 1, $acc * $n);
}
);
var_dump($facTwo(4));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment