Существует ли язык программирования с лучшим подходом для операторов прерывания switch? - PullRequest
18 голосов
/ 10 июня 2010

Это тот же самый синтаксис, что и во многих языках:

switch (someValue) {

  case OPTION_ONE:
  case OPTION_LIKE_ONE:
  case OPTION_ONE_SIMILAR:
    doSomeStuff1();
    break; // EXIT the switch

  case OPTION_TWO_WITH_PRE_ACTION:
    doPreActionStuff2();
    // the default is to CONTINUE to next case

  case OPTION_TWO:
    doSomeStuff2();
    break; // EXIT the switch

  case OPTION_THREE:
    doSomeStuff3();
    break; // EXIT the switch

}

Теперь все, что вы знаете, требуется оператор break, потому что switch будет переходить к следующему case, когда break заявление отсутствует.У нас есть пример этого с OPTION_LIKE_ONE, OPTION_ONE_SIMILAR и OPTION_TWO_WITH_PRE_ACTION.Проблема в том, что нам нужен только этот «переход к следующему делу» очень-очень-очень редко.И очень часто мы ставим перерыв в конце case.

Для новичка очень легко забыть об этом.И один из моих учителей C даже объяснил нам это, как будто это была ошибка в языке C (не хочу говорить об этом:)

Я хотел бы спросить, есть ли другие языки, которые яне знаю (или забыл) о том, что обрабатывает switch / case следующим образом:

switch (someValue) {

  case OPTION_ONE:  continue; // CONTINUE to next case
  case OPTION_LIKE_ONE:  continue; // CONTINUE to next case
  case OPTION_ONE_SIMILAR:
    doSomeStuff1();
    // the default is to EXIT the switch

  case OPTION_TWO_WITH_PRE_ACTION:
    doPreActionStuff2();
    continue; // CONTINUE to next case

  case OPTION_TWO:
    doSomeStuff2();
    // the default is to EXIT the switch

  case OPTION_THREE:
    doSomeStuff3();
    // the default is to EXIT the switch

}

Второй вопрос: есть ли исторический смысл того, почему это так в C?Может быть, продолжить, чтобы следующий случай использовался гораздо чаще, чем мы используем его в наши дни?

Ответы [ 17 ]

11 голосов
/ 10 июня 2010

Из этой статьи я могу перечислить некоторые языки, для которых не требуется выражение break:

  1. Ада (без падения)
  2. Эйфелева (без падения)
  3. Паскаль (без провала)
  4. Go - fallthrough
  5. Perl - continue
  6. Рубин (без падения)
  7. VB, VBA, VBS, VB.NET (без ошибок)
  8. Для продолжения кем-то другим ...

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

9 голосов
/ 10 июня 2010

Сопоставление с шаблоном Scala. Я думаю, что это огромное улучшение в этих случаях :)

object MatchTest2 extends Application {
  def matchTest(x: Any): Any = x match {
    case 1 => "one"
    case "two" => 2
    case y: Int => "scala.Int"
  }
  println(matchTest("two"))
}

Образец с сайта scala-lang.org

6 голосов
/ 10 июня 2010

И VB .NET обрабатывает его немного больше, чем, как вы ожидаете, он должен работать.

Select Case i
    Case 1 to 3
        DoStuff(i)
    Case 4,5,6
        DoStuffDifferently(i)
    Case Is >= 7
        DoStuffDifferentlyRedux(i)
    Case Else
        DoStuffNegativeNumberOrZero(i)
End Select

Никакого провала вообще нет, без использования Goto

4 голосов
/ 10 июня 2010

Вот ответ: http://en.wikipedia.org/wiki/Switch_statement

Он называется резервным оператором (в данном примере continue) и существует на следующих языках:
Go, Perl, C #

В C # он не будет компилироваться без оператора break или goto case (кроме случаев, когда нет предварительных действий).

3 голосов
/ 10 июня 2010

Я думаю, что ответ на ваш вопрос о том, почему это так, основан на двух вариантах поведения, оба из которых связаны с созданным кодом сборки из источника C.

Во-первых, в сборке выполняется текущая инструкция, и, если не будет перехода или какой-либо другой инструкции управления потоком, будет выполнена инструкция по следующему адресу. Выполнение простой компиляции оператора switch в ассемблере сгенерирует код, который просто начнет выполнять первую инструкцию, которая будет проверять, есть ли соответствующее условие ...

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

int atoi(char c) {
  switch (c) {
    case '0': return 0;
    case '1': return 1;
    // ....
  }
}

Наивный компилятор, возможно, просто преобразовал бы это в серию блоков if / then, означая, что для числа 9 будет взято значительное количество циклов ЦП, а 0 возвращается почти сразу. Используя таблицу ветвлений, компилятор может выдать некоторую сборку [psuedo], которая немедленно «перейдет» к правильному предложению возврата:

0x1000 # stick value of c in a register
0x1004 # jump to address c + calculated offset
# example '0' would be 0x30, the offset in for this sample
# would always be 0x0FD8... thus 0x30 + 0x0FD8 = 0x1008
0x1008 # return 0 

Извинения: мои навыки сборки и C довольно ржавые. Я надеюсь, что это помогает прояснить ситуацию. 0x

3 голосов
/ 10 июня 2010

PASCAL не имеет провала

2 голосов
/ 10 июня 2010

Эй, не забывайте ОЦЕНИТЬ КОБОЛА:

EVALUATE MENU-INPUT
    WHEN "0" PERFORM INIT-PROC
    WHEN "1" THRU "9" PERFORM PROCESS-PROC
    WHEN "R" PERFORM READ-PARMS
    WHEN "X" PERFORM CLEANUP-PROC 
    WHEN OTHER PERFORM ERROR-PROC
END-EVALUATE.
1 голос
/ 10 июня 2010

Ада не имеет прорыва и требует, чтобы все значения были явно обработаны, или добавлено предложение "others" для обработки остальных.

Оператор SQL CASE также не работает. XSLT имеет то, что не падает.

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

http://www.adaic.org/whyada/intro4.html

1 голос
/ 10 июня 2010

У Python его нет вообще.

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

1 голос
/ 10 июня 2010

Хотя это не совсем то, что вы просили, в Groovy есть очень мощный оператор switch

...