Почему языки не используют явный провал в выражениях switch?

17

Я читал, почему мы должны использовать breakв switch? и это заставило меня задуматься, почему неявный переход разрешен в некоторых языках (таких как PHP и JavaScript), в то время как нет поддержки (AFAIK) для явного перехода.

Это не continueзначит, что нужно было бы создать новое ключевое слово, как это было бы совершенно уместно, и это решило бы любые вопросы двусмысленности относительно того, намеревался ли автор довести дело до конца.

В настоящее время поддерживаемая форма:

switch (s) {
    case 1:
        ...
        break;
    case 2:
        ... //ambiguous, was break forgotten?
    case 3:
        ...
        break;
    default:
        ...
        break;
}

Принимая во внимание, что имеет смысл записать это как:

switch (s) {
    case 1:
        ...
        break;
    case 2:
        ...
        continue; //unambiguous, the author was explicit
    case 3:
        ...
        break;
    default:
        ...
        break;
}

Для целей этого вопроса давайте проигнорируем вопрос о том, являются ли провалы хорошим стилем кодирования.

Существуют ли какие-либо языки, которые допускают провал и сделали это явным?

Существуют ли какие-либо исторические причины, которые switchдопускают явный провал вместо явных?

zzzzBov
источник
4
C # требует, чтобы вы были откровенны goto case, поэтому предпосылка вашего вопроса несколько ошибочна.
фунтовые
1
@pdr, я очень четко спросил, есть ли языки, которые уже поддерживают переход, я не знал об этом goto caseв C #.
zzzzBov
Да, извини, я пропустил, что на твой вопрос было две части. К сожалению, как бы это ни было сказано, я голосую за закрытие, потому что это очень близко к вопросу об опросе. Там будет много правильных ответов.
фунтовые
C # также позволяет нескольким меткам совместно использовать один и тот же список операторов, что устраняет некоторые ситуации, требующие провала. В остальном goto case, как упоминает pdr.
Брайан

Ответы:

20

Это в первую очередь историческое, большинство языков просто скопировали то, что сделал С.

Причина, по которой C сделал это таким образом, заключается в том, что создатели C предполагали, что операторы switch легко оптимизировать в таблицу переходов. Это также причина того, что C ограничивает операторы switch интегральными значениями.

В таблице переходов программа рассчитает, на какую позицию перейти, основываясь на выражении. Программа перейдет к этой точке, а затем продолжит выполнение с этой точки. Если вы хотите пропустить оставшуюся часть таблицы, вы должны включить переход к концу таблицы. C использует явные breakутверждения, так что есть прямое соответствие этой конструкции.

Дирк Холсоппл
источник
7
В качестве небольшой заметки, в своей книге «Программирование на Expert C» Питер ван дер Линден упоминает, что, когда он работал на Sun над их компилятором C, содержалось около ~ 97% случаев переключения, breakи только менее 3% были провальными. , Затем он использовал это в качестве примера того, что стандартное поведение сброса является нелогичным и было бы лучше быть обратным (используйте ключевое слово для обозначения явного перехода). О, и книга действительно хороша для объяснения других странностей C, некоторые из которых можно найти в C ++ и даже в C # и Java! Это все коренится в B и BCPL. :)
zxcdw
3
Существуют языки программирования, где провал явно, например, c # ( msdn.microsoft.com/en-us/library/06tc147t(v=vs.71).aspx ). С другой стороны, нарушение также явно в C #.
linkerro
@zxcdw: Жаль, что небольшая птичка не может вернуться в прошлое и предложить, чтобы к любому ярлыку case, отличному от первого, был автоматически добавлен префикс break, а для помеченного +case(или какого-либо другого такого обозначения) - нет. Это было бы легко для компилятора и позволило бы использовать семантические преимущества существующей схемы, исключая при этом множество строк кода.
суперкат
7

Go допускает явное падение с помощью fallthroughключевого слова (break неявный, но может быть явным):

switch val {
case 1: // breaks
case 2:
    fallthrough
case 3:
    goto 
case 4, 5, 6: // equivalent to defining individual cases with explicit fallthough
    break // unnecessary
default:
}

Вот соответствующий бит от эффективного go и спецификации языка .

Я не думаю, что вы можете использовать, gotoчтобы перейти к конкретному случаю, но вы можете сделать ярлык внутри корпуса и использовать gotoкак обычно.

В качестве бонуса Go позволяет вам использовать бинарные выражения, строки или типы в переключателе в качестве операторов case.

beatgammit
источник