Есть ли язык программирования с лучшим подходом для операторов завершения переключателя?

Это - тот же синтаксис способом слишком много языков:

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 (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? Может быть продолжаются к следующему случаю, использовался намного чаще, чем мы используем его в эти дни?

18
задан m_vitaly 10 June 2010 в 13:17
поделиться

16 ответов

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

  1. Ada (без отступления)
  2. Eiffel (без отступления)
  3. Pascal (без отступления)
  4. Go - отступление
  5. Perl - продолжение
  6. Ruby (без отступления)
  7. VB, VBA, VBS, VB. NET (без отступления)
  8. Продолжит кто-то другой...

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

11
ответ дан 30 November 2019 в 06:54
поделиться

языков слишком много, и я не могу с уверенностью сказать, что такого языка не существует, при условии, что он является «производным» от C в синтаксисе, потому что другие языки, использующие другой синтаксис и где регистр не «продолжается», естественно, существуют, например Фортран. Я не знаю языков, в которых используется явное «continue» для перехода к следующему случаю.

Я считаю, что это историческая причина из-за того, что такой случай может быть запрограммирован на «низком уровне». Более того, синтаксический аспект case - это метка, а break работает как в циклах, так что вы можете представить себе эквивалент, подобный этому:

if ( case == 1 ) goto lab1;
if ( case == 2 ) goto lab2;
if ( case == 3 ) goto lab3;    
//...
default:
  // default
  goto switch_end;
lab1:
  // do things
  goto switch_end; // if break is present
lab2:
  // do things, and follow to lab3
lab3:
  // lab3 stuffs
  goto switch_end;
//
...
switch_end:  // past all labS.
0
ответ дан 30 November 2019 в 06:54
поделиться

В объектно-ориентированных языках используется шаблон Цепочка ответственности . То, как это реализовано, может варьироваться. В своем примере вы описываете смешивание конечного автомата с поведением, злоупотребляя оператором switch. Для вашего конкретного примера подходящей реализацией будет шаблон цепочки ответственности с параметром, который цепочка оценивает как шаблон Состояние , который видоизменяется по мере продвижения вниз по цепочке.

0
ответ дан 30 November 2019 в 06:54
поделиться

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

1
ответ дан 30 November 2019 в 06:54
поделиться

Tcl не проваливается автоматически.

0
ответ дан 30 November 2019 в 06:54
поделиться

OP говорит о «провале», но меня это очень редко когда-либо укусило.

Тем не менее, много раз я был поражен нерасширяемыми проектами. А именно, утверждения «switch (kbHit)» с несколькими сотнями ключей внутри - кошмар обслуживания, частое место для «божественных методов» и гигантских груд спагетти-кода.

Использование переключателя часто является признаком плохого объектно-ориентированного программирования. Как ответил другой человек, «2 использования Switch в 48 исходных файлах» в одном из его приложений показывают программиста, который не слишком полагается на эту конструкцию. Судя по его метрике, я предполагаю, что он, вероятно, по крайней мере, хороший структурированный программист и, вероятно, также понимает ООП / ООД.

Программисты ООП (не обязательно только на C ++) и даже чистые пользователи C, которым не навязана техника описания объектов, могут реализовать контейнер «инверсии управления», который публикует «нажатие клавиши» и позволяет подписчикам подключите их обработчики для "кода клавиатуры x". Это может значительно упростить чтение вашего кода.

1
ответ дан 30 November 2019 в 06:54
поделиться

Ada не имеет провалов и требует, чтобы все значения обрабатывались явным образом или добавлялось предложение «другие» для обработки остальных.

Оператор SQL CASE также не дает сбоев. XSLT не проваливается.

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

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

1
ответ дан 30 November 2019 в 06:54
поделиться

Эй, не забудь ОЦЕНКА КОБОЛА:

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.
2
ответ дан 30 November 2019 в 06:54
поделиться

PASCAL не имеет fall-through

3
ответ дан 30 November 2019 в 06:54
поделиться

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

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

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

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

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

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 

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

3
ответ дан 30 November 2019 в 06:54
поделиться

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

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

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

4
ответ дан 30 November 2019 в 06:54
поделиться

Python не имеет его вообще .

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

1
ответ дан 30 November 2019 в 06:54
поделиться

А 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

6
ответ дан 30 November 2019 в 06:54
поделиться

Scala pattern matching я считаю огромным улучшением в этих случаях. :)

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

9
ответ дан 30 November 2019 в 06:54
поделиться

Больше языков без fallthough:

XSLT JSTL Алгол PL/1

0
ответ дан 30 November 2019 в 06:54
поделиться

Чистая спекуляция, но:

Я иногда пишу C или Java, в которых говорю что-то вроде:

switch (tranCode)
{
  case 'A':
  case 'D':
  case 'R':
    processCredit();
    break;
  case 'B':
  case 'G':
    processDebit();
    break;
  default:
    processSpecial();
}

То есть я намеренно использую fall-thru, чтобы позволить нескольким значениям запускать одну и ту же операцию.

Интересно, если это то, о чем думали изобретатели C, когда они создавали заявление SWITCH, что это было бы нормальным использованием.

1
ответ дан 30 November 2019 в 06:54
поделиться