模仿PHP 5.2中的goto功能-可能是更好的方法



我使用本地PHP 5.3安装编写了一个脚本,其中使用了goto语句。把它上传到我的服务器上,我不得不发现我的主机仍然安装了PHP 5.2,因此不支持goto。因此,我的问题是如何在以下上下文中模拟goto的功能:

foo();
iterator_start:
foreach ($array as $array_item) {
    switch ($array_item) {
        case A:
            foo();
            break;
        case B:
            // Substitute
            array_splice($array, offset($array_item), 1, array(A, A, B, C));
            // Restart iterator
            goto iterator_start;
            break;
    }
}

这个想法是数组必须根据一组替换规则进行修改。一旦执行了规则(可以修改任何位置的任意数量的数组项,替换它们,甚至删除它们),一切都必须从零开始,因为整个数组可能以不可预测的方式发生了变化(因此也允许递归替换规则)。我使用的解决方案,goto在每次替换后简单地跳到循环的开始,对我来说似乎非常直接,甚至非常干净,但正如我提到的,我不能在我的web服务器上使用它。

这里是否有goto的替代品,或者可以用完全不同的方式完成相同的任务(最好不改变太多代码)?

欢迎大家多多指教。


一个礼貌的请求:请不要再给我讲goto的有用性或危险了。我读过PHP和将要在PHP 5.3中添加的goto语句,也知道意大利面条式代码和所有那些从20世纪80年代开始流行的"被认为有害的"字母。讨论goto的所谓邪恶与我的问题无关,将任何程序结构视为"坏风格"本身只是教条,在我的编程思想中没有地位。

可以在while循环中使用each()。它使用内部数组游标检索数组中的当前元素,并将游标移动到下一个元素。在对数组进行切片时,重置为游标,以便在下一个while循环迭代时从数组的起点重新开始。调用reset()可能不是必需的,它可能是array_splice()的副作用,因为它改变了数组。

foo();
while (list($key, $array_item) = each($array)) {
  switch ($array_item) {
    case A:
      foo();
      break;
    case B:
      // Substitute
      array_splice($array, offset($array_item), 1, array(A, A, B, C));
      // Reset array cursor, this is probably not necessary 
      reset($array);
      break;
  }
}

递归?与goto iterator_start不同,您将这个循环包装在一个函数中,并递归地调用它。

嗯,据说任何goto都可以用forwhile之类的控制结构或函数来代替。

在你的例子中,我会使用一个函数:

function goto_substitute($array){
foreach ($array as $array_item) {
    switch ($array_item) {
        case A:
            foo();
            return $array;
        case B:
            // Substitute
            array_splice($array, offset($array_item), 1, array(A, A, B, C));
            // Restart iterator
            return goto_substitute($array) ;                
    }
}
}

编辑(处理注释)

Functions使代码更易读。编程最佳实践说,一个函数应该做一个单一的事情和不超过一个屏幕的大小(大约80-90行)-你有多个替代块-似乎有多个函数是合乎逻辑的-如果你直观地命名它们,那么任何人都能理解那里发生了什么

是否尝试使用include?比如你把foreach代码写在

文件中

foreach。php不使用goto而是使用include('foreach。php')

foreach ($array as $array_item) {
switch ($array_item) {
    case A:
        foo();
        break;
    case B:
        // Substitute
        array_splice($array, offset($array_item), 1, array(A, A, B, C));
        // Restart iterator
        include('foreach.php'); 
        break;
}

}

goto是远古时代的邪恶神器。没有人知道为什么在PHP 5.3中引入它。不要用它。。

这是Dijkstra的一个很好的解释,甚至表明自1959年以来它一直被一些人皱眉。随着越来越多的控制流语句出现,goto的需求就更少了。在优化一些低级的、时间关键的代码时,它可能有特定的用途,但绝对没有理由在PHP中使用它,而且我还没有看到goto比其他任何解决方案都更好的第一个例子。

对于您的情况,递归可能是最好的解决方案。

最新更新