diff --git a/LambdaExtension.php b/LambdaExtension.php index a62b05f..b584f70 100644 --- a/LambdaExtension.php +++ b/LambdaExtension.php @@ -19,13 +19,13 @@ public function getOperators() { return [ [ - '=>' => [ + '==>' => [ 'precedence' => 0, 'class' => '\DPolac\TwigLambda\NodeExpression\SimpleLambda' ], ], [ - '=>' => [ + '==>' => [ 'precedence' => 0, 'class' => '\DPolac\TwigLambda\NodeExpression\LambdaWithArguments', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT @@ -67,6 +67,7 @@ public function getFilters() new \Twig_SimpleFilter('group_by', '\DPolac\TwigLambda\LambdaExtension::groupBy'), new \Twig_SimpleFilter('sort_by', '\DPolac\TwigLambda\LambdaExtension::sortBy'), new \Twig_SimpleFilter('count_by', '\DPolac\TwigLambda\LambdaExtension::countBy'), + new \Twig_SimpleFilter('unfold', '\DPolac\TwigLambda\LambdaExtension::unfold'), ]; } @@ -292,9 +293,28 @@ public static function call($callback, array $args = []) } return call_user_func_array($callback, $args); } + + public static function unfold($state, $callback, array $unfolded = []) + { + if (!is_callable($callback)) { + throw new \InvalidArgumentException('First argument must be callable.'); + } + + while (true) + { + $retval = $callback($state); + if (is_null($retval)) + break; + + list ($newVal, $state) = $retval; + $unfolded[] = $newVal; + } + + return $unfolded; + } public function getName() { return 'dpolac_lambda_extension'; } -} \ No newline at end of file +} diff --git a/README.md b/README.md index 618c537..48f7fb9 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,22 @@ Returns array of elements that passes a test specified by lambda. ---------------------------------------------------------------- + +### |unfold +**Signature:** `state|unfold(lambda[, retval = []])` + +Given a lambda that returns an array `[value, state]` or `null`, repeatedly +calls the function until it returns `null`, passing the new `state` on each +call. Returns an array of the accumulated values. + + +```twig +{% do [1, 1]|unfold(=> _[1] > 1000 ? null : [ _[0] + _[1], [ _[1], _[0] + _[1]]], [1, 1]) %} +{# Calculates the Fibonacci numbers up to and including 1597. #} +``` + +---------------------------------------------------------------- + ### |unique_by **Signature:** `array|unique_by(lambda|'==='|'==')`