【问题标题】:Recursion with anonymous function [duplicate]使用匿名函数递归[重复]
【发布时间】:2011-10-26 17:10:18
【问题描述】:

可能的重复:
javascript: recursive anonymous function?
Anonymous recursive PHP functions

我想知道...是否可以使用匿名函数进行递归?

这是一个例子:我需要得到一个可能只包含数字和空格的六字符长字符串。唯一的规则是它不能以空格开头或结尾。我们检查它,如果发生这种情况 - 只需在相同的匿名函数上调用递归。怎么样!?

function() {

    $chars   = range(0, 9);
    $chars[] = ' ';
    length   = 6;
    $count   = count($chars);

    $string = '';
    for ($i = 0; $i < $length; ++$i) {

        $string .= $chars[mt_rand(0, $count - 1)];

    }

    $string = trim($string);

    if (strlen($string) !== $length) { // There were spaces in front or end of the string. Shit!

        // Do recursion.

    }

    return $string;

}

【问题讨论】:

标签: php recursion reference anonymous-function anonymous-recursion


【解决方案1】:

是的,但我不推荐它,因为它有点棘手;)

第一种可能性:

<?php
$some_var1="1";
$some_var2="2";
function($param1, $param2) use ($some_var1, $some_var2)
{
    call_user_func(__FUNCTION__, $other_param1, $other_param2);
}
?>

另一个:

<?php 
$recursive = function () use (&$recursive){ 
    // The function is now available as $recursive 
} 
?> 

示例取自http://php.net/

【讨论】:

  • 感谢第二种方式。在我看来,这是最好的方法。
  • +1 第二个真的很优雅!我一直认为你需要使用那个看起来很疯狂的 Y-Combinator 来做 Lambda-Recursion ;)
【解决方案2】:

答案很复杂,但并非不可能。我花了几分钟才弄清楚。我们首先必须定义一个名为 $combinator() 的实用函数。

你的问题的解决方案:

$combinator(
function($self) { function() use (&$self) {
    $chars   = range(0, 9);
    $chars[] = ' ';
    length   = 6;
    $count   = count($chars);

    $string = '';
    for ($i = 0; $i < $length; ++$i) {
        $string .= $chars[mt_rand(0, $count - 1)];
    }
    $string = trim($string);

    if (strlen($string) !== $length) {
        return $self();
    }
    return $string;
} }
);

$combinator()的定义:

$combinator = function($principle)
{
  (function($transept) use (&$principle)
  {
    $principle(
      function($arguments) use (&$transept)
      {
        call_user_func_array($transept($transept), $arguments));
      }
    );
  })
  (function($transept) use (&$principle)
  {
    $principle(
      function($arguments)
      {
        call_user_func_array($transept($transept), $arguments);
      }
    );
  });
}

【讨论】:

    【解决方案3】:

    做同样事情的更明智的方法。也只需要一个循环。

    $chars = array_merge(range(0, 9), array(' '));
    
    $string = mt_rand(0, 9);
    for ($i = 1; $i <= 4; $i++) {
        $string .= $chars[array_rand($chars)];
    }
    $string .= mt_rand(0, 9);
    

    很抱歉回避了实际问题。

    【讨论】:

    • 嘿,谢谢。会记住的。 :)
    【解决方案4】:

    使用转到

    function() {
        start:
        $chars   = range(0, 9);
        $chars[] = ' ';
        length   = 6;
        $count   = count($chars);
    
        $string = '';
        for ($i = 0; $i < $length; ++$i) {
    
            $string .= $chars[mt_rand(0, $count - 1)];
    
        }
    
        $string = trim($string);
    
        if (strlen($string) !== $length) { // There were spaces in front or end of the string. Shit!
    
            goto start;
    
        }
    
        return $string;
    

    但使用 goto 并不是最好的办法。

    【讨论】:

    • 在这项工作期间,我强烈建议您不要使用 gotos。用带有 args 的真实函数替换你的函数并在那里进行递归是最好的选择。
    • @AlexisMétaireau:是的,我认为这是更好的主意,但 OP 想用匿名函数来做,所以我认为你没有理由反对
    • downvoter:你愿意解释一下吗?
    • 这个答案基本上是说:我不知道如何做递归匿名函数,所以我用 goto 作弊
    • @genesis 您可以只使用ifgoto 编写整个脚本,而不是使用forwhile 或函数或类。但是以这种方式编写的脚本是回到 70 年代的一步。我们不再以这种方式编写代码,因为我们现在有更好的工具来完成这项工作。见secure.wikimedia.org/wikipedia/en/wiki/…stackoverflow.com/questions/46586/goto-still-considered-harmfulstackoverflow.com/questions/4843551/…
    猜你喜欢
    • 2022-06-20
    • 2015-11-21
    • 2011-01-29
    • 2011-04-22
    • 2020-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    相关资源
    最近更新 更多