【问题标题】:Why is a `switch` considered a looping structure for the purposes of `continue`?为什么'switch'被认为是'continue'的循环结构?
【发布时间】:2012-01-26 19:47:06
【问题描述】:

我只是假设以下几点:

foreach ($arr as $key => $value) {
  switch($key) {
    // ... some other cases
    default:
      continue;
      // ^== assumption: move on to the next iteration of the foreach
      //     actual PHP: treat this continue just like a break
  }
  // ...
}

但其实根据documentation for continue:

出于继续的目的,switch语句被认为是一个循环结构。

PHP 语言设计者有这样的选择吗?据我所知,switch 不是循环控制结构,那么为什么在这种情况下将其视为一个呢?

【问题讨论】:

  • 在谈论php 时,应避免使用“原因”和“设计”这两个词;)
  • 你可以使用continue 2 =)
  • @drrcknlsn, switch 需要保持一致,因为它使用了跳出活动块的break。顺便说一句,这都是我的猜测。
  • @zzzzBov 我们谈论的是continue,它用于循环结构以跳到下一个迭代。它应该忽略switch。 break 两者都可以,应该跳出块或循环。在此用例中,将switch 视为循环结构实质上使continue 与break 同义。
  • @chesles,如果你在一个块上使用continue,它会跳出活动块并继续到该块的下一次迭代。我可以将switch 想象成一个循环结构,只有一次迭代,这将使continue 的行为与break 相同,完成循环并移出块。我不是在为语言的设计辩护,我只是在推测我看到的模式。

标签: php loops switch-statement


【解决方案1】:

我能想到的最好解释是 PHP 认为它是一个循环结构,因此它适合使用 continue 和 break 的模型。 switch 文档除了

之外没有进一步阐明它

请注意,与其他一些语言不同,continue 语句适用于 switch,其作用类似于 break。如果您在循环内有一个开关,并希望继续到外循环的下一次迭代,请使用 continue 2。

也许是因为,就像循环一样,它停止执行其结构中的其余代码。

但是,当您使用多个级别时,这两个级别的行为完全不同:

continue 没有等级

<?php
for($i=0;$i<5;$i++) {
    switch($i) {
        case 2:
            continue;
        default:
            echo $i, "\n";
    }
    echo "Finished with {$i}\n";
}
//0
//Finished with 0
//1
//Finished with 1
//Finished with 2
//3
//Finished with 3
//4
//Finished with 4

continue有等级

<?php
for($i=0;$i<5;$i++) {
    switch($i) {
        case 2:
            continue 2;
        default:
            echo $i, "\n";
    }
    echo "Finished with {$i}\n";
}
//0
//Finished with 0
//1
//Finished with 1
//3
//Finished with 3
//4
//Finished with 4

break 没有等级

<?php
for($i=0;$i<5;$i++) {
    switch($i) {
        case 2:
            break;
        default:
            echo $i, "\n";
    }
    echo "Finished with {$i}\n";
}
//0
//Finished with 0
//1
//Finished with 1
//Finished with 2
//3
//Finished with 3
//4
//Finished with 4

break有等级

<?php
for($i=0;$i<5;$i++) {
    switch($i) {
        case 2:
            break 2;
        default:
            echo $i, "\n";
    }
    echo "Finished with {$i}\n";
}
//0
//Finished with 0
//1
//Finished with 1

【讨论】:

    【解决方案2】:

    我认为您不会为这种行为找到任何真正的“原因”。

    这种行为背后的唯一真正动机可能是实现switch 就好像它是一个循环结构允许PHP 重用现有的break 和continue 循环语义,而不是重新实现switch 的特殊版本。

    或者更积极地说:这是为了一致性。

    【讨论】:

    • 所以,“他们很懒惰”?有道理,我猜:P
    • switch 表达式针对每种情况(case、default)进行评估,直到循环完成(代码块结束或直到 break、continue 或 @ 987654331@ 已给出)。
    • @hakre 不正确。 “在 switch 语句中,条件只计算一次,结果与每个 case 语句进行比较” - php.net/manual/en/control-structures.switch.php
    • 我不确定一致性,因为它与例如 C 中的 switch/continue 不一致。但是,在 PHP 源代码中进行了一些处理之后,它似乎确实是为了简单起见实施continue。由于它与关注开关块的break关系密切,所以continue也关注它们。
    【解决方案3】:

    据我所知,switch 不是循环控制结构,那么为什么在这种情况下将其视为循环控制结构呢?

    一次迭代不符合循环条件吗?同样适用于foreach 内的while,例如只迭代一次:

    foreach (range(1,2) as $value)
    {
        $i = 0;
        while (!$i++)
        {
           continue;
        }
        echo $value, "\n";
    }
    

    它也会回显这些值,而不是 continue foreach 循环;与while相关。

    如果您的期望是 switch 与 if 类似(事实并非如此),那么您可能不会期望 continue 的行为,但是我很确定 while 您会期望它。

    但如果你真的认为if 就像switch,那么break 与continue 的工作方式有何不同?

    所以我不会说它有什么问题,只是switch 是一个具有循环衣服的控制结构。由于我们通常使用break(您希望它可以工作),continue 的行为并不为人所知。就这样。或者你为什么期望continue 不能像switch 中的break 那样工作?

    所以可能的原因是 break 和 continue 对齐。

    【讨论】:

    • 我的期望是 switch 就像if/else if 的字符串,除非我弄错了。一些没有 switch 的语言(例如 python)甚至说“使用 if/elif 而不是 switch”。那么 switch 怎么不像 PHP 中的 if 呢?
    • "switch 语句类似于同一个表达式上的一系列 IF 语句。" - php.net/manual/en/control-structures.switch.php
    • @chesles:好吧,很酷,这就是我的假设(好像脑子里有开关)——所以类比是break 和continue。您是否希望它们也能正常工作(对于 break 和 continue,与 if 和 switch 相同)?
    • 查看我的问题,我在其中描述了我期望的行为。本质上,我希望continue 继续最近循环的下一次迭代,并且我不希望switch 成为一个循环,因为它不是,尽管 PHP 出于某种原因将它视为一个循环。这个原因就是我在这里所追求的。
    • 那么break呢?您对switch 中的break 有何期待?打破最近的循环,你不希望switch 成为那个循环,对吧?请记住,任何循环也是一个控制结构。
    猜你喜欢
    • 1970-01-01
    • 2010-12-26
    • 1970-01-01
    • 2014-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    相关资源
    最近更新 更多