如何在PHP中传递标签?

时间:2016-03-25 08:47:49

标签: php lambda goto

这个故事的背景很长,所以为了保持简短 - 我知道goto很糟糕,但我别无选择,因为...... PHP缺少逗号运算符。

我有这样的模式 - 常规函数,其入口点作为标签给出,并且在其内部是一个小的lambda,需要goto到该入口点。像这样的东西(错误的代码):

  function water()
  {
    _Entry_point_2_0:
    // ... some code
    (function() { /*...*/ ;goto _Entry_point_2_0;})();
    // ... some code
  }

我不能只跳过函数边界,所以我的下一个想法是从lambda返回标签并将其用作" value"为了转到。像这样:

  function water()
  {
    _Entry_point_2_0:
    // ... some code
    goto (function() { /*...*/ ;return '_Entry_point_2_0';})();
    // ... some code
  }

这不起作用。将整个goto评估为字符串eval ('goto _Entry_point_2_0;')也不起作用。

疯狂的部分是我事先知道标签,所以你可以问为什么我不能写出这样的全部功能:

  function water()
  {
    _Entry_point_2_0:
    // ... some code
    (function() { /*...*/ ;})();
    goto _Entry_point_2_0;
    // ... some code
  }

问题在于逻辑 - 执行lambda goto现在制作2个表达式,而不是一个。我需要在一个表达式中创建它 - 执行lambda和goto必须打包在单个表达式中。

我也不能递归调用main函数,因为它是这项工作的全部要点,以避免递归调用: - )。

实现这一目标的其他方法是什么?

更新1 也许我改写一下 - 我想用goto实现的是continue my_function。从内部函数(即lambda)的边界处或在其内部执行。

更新2 主要目标是循环使用main函数,因此几乎相当于:

  function water()
  {
    _Entry_point_2_0: while (true)
    {
      // ... some code
      continue (function() { /*...*/ ; return '_Entry_point_2_0'; })();
      // ... some code
    }
  }

"几乎"因为两个原因。我仍然像以前一样对标签有问题,现在我还有什么问题在哪里将break添加到循环中。

4 个答案:

答案 0 :(得分:3)

因此,您无法从匿名/ lambda函数中跳过循环迭代。但是你可以返回一个值,比较main函数中的值,然后从那里跳过迭代。听起来很简单,对吧?

编辑:如果你也想要从lamba中断,你可以使用相同的策略。

function water() {
    $lambda = function() { /*...*/; };

    while (true) {
        // Call the lambda function and store the return value.
        $return = $lambda();

        // If the return value was 'skip this iteration', well... skip it.
        // Note: I'd normally compare to false, null or similar.
        if ($return == 'skip this iteration') {
            continue;
        }
        elseif ($return == "we're done!") {
            break;
        }

        // Do stuff here.
    }
}
  

我需要在一个表达式中创建它 - 执行lambda和goto必须打包在单个表达式中。

所以从你上次的评论中,我现在部分理解你为什么要这个要求。但它仍然不完全清楚。您编写了一个脚本,将此代码注入到一些预先存在的函数中,并且不了解周围环境。但是goto标签已经到位了吗?无论如何,也许您的问题就像这样简单:您希望代码只是一个。但这是可能的,代码可以只跨越PHP中的一行。它不是最漂亮的,但效果很好。

function water() {
    while (true) {
        if (function() { /*...*/; }() == 'skip this iteration') { continue; /* Or goto */ }
        // Do stuff here.
    }
}

答案 1 :(得分:1)

我相当确定这是不可能的设计。

Annonymous functions要求所有"州"通过使用声明传递。您不能将标签作为参考传递

  

PHP Parse错误:语法错误,意外' _Entry_point_2_0'   (T_STRING),期待'&'或变量(T_VARIABLE)

该函数在其自己的作用域中运行,没有引用标签,这意味着它需要以某种方式传回。

goto docs有以下

This is not a full unrestricted goto. The target label must be within the same file and context, meaning that you cannot jump out of a function or method, nor can you jump into one.

将变量传递给goto

也无效
PHP Parse error:  syntax error, unexpected '$goto' (T_VARIABLE), expecting identifier (T_STRING)

虽然所有这些都可能是一件好事,但是当goto认为逻辑流程是错误的时候,你将能够找到一种方法来构建更具核心性但不需要去的方法。

编辑:

更新后2为什么不做

 if(your lambda() == something) {
        Continue;
 }

抱歉在手机上写了代码。这似乎做了同样的事情,而且更具可读性

答案 2 :(得分:1)

也许您正试图解决您的问题解决方案而不是原始问题。这个问题有点XY problem

_Entry_point_2_0:
    // ... some code
    (function() { /*...*/ ;goto _Entry_point_2_0;})();

do while循环那样找我:

do {
    // ... some code
} while ((function() { /*...*/ ; return $k !== 0;})());

现在不允许应用这样的匿名函数。此外,需要显式声明闭包参数。因此我的解决方案需要这样写:

$k = 10;
$f = function() use (&$k) { /*...*/ ; return $k !== 0; };
do {
    // some code
} while ( $f() );

如果你想要一个"逗号运算符"你只需要制作一个能够接受任何数量的争论并返回最后一个的函数:

function begin(){
    return func_get_args()[func_num_args()-1];
}

begin(expression1, expression2, expression3); // ==> result of expression3

所有函数参数都会被评估,因此它会在参数不相互依赖的情况下执行相同的操作。

答案 3 :(得分:0)

您可以使用递归:

function myFunc($i = 0) {
    if ($i < 10) { //or any other logic to prevent "infinite loop"
        //Main code
        myFunc($i++);
    }
}