这个故事的背景很长,所以为了保持简短 - 我知道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
添加到循环中。
答案 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++);
}
}