Подтвердить что ты не робот

Почему `switch` считается циклической структурой для целей` continue`?

Я просто получил бит, предположив следующее:

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
  }
  // ...
}

Но на самом деле, согласно документации для продолжения:

оператор switch считается структурой цикла для продолжения.

Есть ли причина для этого выбора со стороны разработчиков языка PHP? Насколько я могу судить, switch не является структурой управления циклом, поэтому зачем относиться к ней как к одному в этом случае?

4b9b3361

Ответ 1

Я думаю, что вы не найдете реальной причины для этого поведения.

Единственная реальная мотивация этого поведения, вероятно, заключалась в том, что реализация switch, как если бы это была структура цикла, позволяет PHP повторно использовать существующие семантики циклов break и continue вместо переопределения специальной версии для switch.

Или выразить это более позитивно: это для согласованности.

Ответ 2

Лучшее объяснение, о котором я могу думать, заключается в том, что PHP считает его циклической структурой, поэтому он подходит для модели того, что использует continue и break. Документация switch не проливает больше света на нее, кроме

Обратите внимание, что в отличие от некоторых других языков оператор continue применяется к коммутатору и действует подобно 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

Ответ 3

Насколько я могу судить, switch не является структурой управления циклом, поэтому зачем относиться к ней как к одному в этом случае?

Существует ли одна итерация не как цикл? То же самое относится к while внутри foreach, например, только однократно:

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 не будет работать как break в switch?

Таким образом, причина может заключаться в выравнивании break и continue.