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

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

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

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

4b9b3361

Ответ 1

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

  • Ada (нет провала)
  • Эйфель (без провала)
  • Паскаль (без провала)
  • Go - fallthrough
  • Perl - continue
  • Ruby (нет провала)
  • VB, VBA, VBS, VB.NET(без провала)
  • Продолжение следует кем-то еще...

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

Ответ 2

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

Ответ 3

И 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

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

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

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

Ответ 5

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

Ответ 6

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

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

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

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

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

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

Ответ 7

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

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.

Ответ 8

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

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

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

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

Ответ 9

У Python его нет.

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

Ответ 11

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

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

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

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

Ответ 12

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

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

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

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

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

Ответ 13

Tcl не проходит автоматически.

Ответ 14

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

Ответ 15

Языки

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

Я считаю, что это историческая причина из-за того, что такой случай можно запрограммировать на "низком уровне". Более того, синтаксический аспект дела - это ярлык ярлыка, а 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.

Ответ 16

Другие языки без слайдов:

XSLT JSTL Алголь PL/1

Ответ 17

Лима делает это так:

if someValue == ?1 ::
   OPTION_ONE: fall
   OPTION_LIKE_ONE: fall
   OPTION_ONE_SIMILAR:
     doSomeStuff1[]
     ;; the default is to EXIT the switch

   OPTION_TWO_WITH_PRE_ACTION:
     doPreActionStuff2[]
     fall                 ;; fall through to the next case

   OPTION_TWO:
     doSomeStuff2[]

   OPTION_THREE:
     doSomeStuff3[]