Dlaczego języki nie używają jawnego przewrotu instrukcji przełączania?

17

Czytałam Dlaczego mamy do wykorzystania breakw switch? i doprowadziło mnie do zastanowienia się, dlaczego niejawne przejście jest dozwolone w niektórych językach (takich jak PHP i JavaScript), podczas gdy nie ma wsparcia (AFAIK) dla jawnego przejścia.

To nie jest tak, że trzeba utworzyć nowe słowo kluczowe, co continuebyłoby idealnie odpowiednie, i rozwiązałoby wszelkie niejednoznaczne kwestie dotyczące tego, czy autor chciał, aby sprawa się zakończyła.

Aktualnie obsługiwany formularz to:

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

Mając na uwadze, że sensowne byłoby napisanie go jako:

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

Na potrzeby tego pytania zignorujmy kwestię, czy pomyłki są dobrym stylem kodowania.

Czy istnieją jakieś języki, które pozwalają na awarię i wyraźnie ją wyrażają?

Czy istnieją jakieś historyczne powody, które switchpozwalają na domniemany upadek zamiast jawnego?

zzzzBov
źródło
4
C # wymaga, abyś był jawny goto case, więc przesłanka twojego pytania jest nieco błędna.
pdr
1
@pdr, bardzo wyraźnie zapytałem, czy są jakieś języki, które już obsługiwały awarie, których nie znałem goto casew C #.
zzzzBov
Tak, przepraszam, tęskniłem za tym, że twoje pytanie składało się z dwóch części. Niestety, wyrażony w obecnym brzmieniu, głosuję za zamknięciem, ponieważ jest bardzo blisko pytania dotyczącego ankiety. Będzie wiele poprawnych odpowiedzi.
pdr
C # pozwala również, aby wiele etykiet dzieliło tę samą listę instrukcji, co usuwa niektóre sytuacje wymagające przewrotu. Resztę ma goto case, jak wspomina pdr.
Brian

Odpowiedzi:

20

Jest to przede wszystkim historyczne, większość języków po prostu skopiowała to, co zrobił C.

Powodem, dla którego C zrobił to w ten sposób, jest to, że twórcy C chcieli, aby instrukcje przełączników były łatwe do optymalizacji w tabeli skoków. Jest to również powód, dla którego C ogranicza instrukcje przełączania do wartości całkowitych.

W tabeli skoków program obliczy, do której pozycji przeskoczyć na podstawie wyrażenia. Program przejdzie do tego punktu, a następnie będzie kontynuował wykonywanie od tego miejsca. Jeśli chcesz pominąć resztę stołu, musisz dołączyć skok na koniec stołu. C używa jawnych breakinstrukcji, dzięki czemu istnieje bezpośrednia zgodność z tym konstruktem.

Dirk Holsopple
źródło
7
Jako małą notatkę, w swojej książce „Expert C Programming” Peter van der Linden wspomina, że ​​podczas gdy pracował dla Sun nad ich kompilatorem C, około ~ 97% skrzynek przełączników zawierało, breaka tylko mniej niż 3% było wadliwych . Następnie wykorzystał to jako przykład, że domyślne zachowanie przejściowe jest sprzeczne z intuicją i lepiej byłoby odwrócić (użyj słowa kluczowego, aby wskazać wyraźny błąd awaryjny). Aha, i ta książka naprawdę świetnie tłumaczy inne dziwactwa C, niektóre z nich można znaleźć w C ++, a nawet w C # i Javie! Wszystko jest zakorzenione w B i BCPL. :)
zxcdw
3
Istnieją języki programowania, w których przejście jest jawne, na przykład c # ( msdn.microsoft.com/en-us/library/06tc147t(v=vs.71).aspx ). Z drugiej strony, łamanie jest również jawne w c #.
linkerro
@zxcdw: Szkoda, że ​​mały ptak nie może cofnąć się w czasie i sugerować, że każda oznaczona etykieta case, inna niż pierwsza, powinna być automatycznie poprzedzona prefiksem break, ale te oznaczone +case(lub jakiś inny taki oznacznik) nie powinny. Kompilator byłby łatwy w obsłudze i pozwoliłby na semantyczne zalety obecnego układu, eliminując jednocześnie wiele wierszy kodu.
supercat
7

Go pozwala na jawny przegląd za pomocą fallthroughsłowa kluczowego (przerwa jest niejawna, ale może być jawna):

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:
}

Oto odpowiedni fragment ze skutecznej wersji i specyfikacja języka .

Nie sądzę, że możesz użyć, gotoaby przejść do konkretnego przypadku, ale możesz zrobić etykietę wewnątrz skrzynki i użyćgoto jak zwykle.

Jako bonus, Go pozwala używać wyrażeń binarnych, ciągów lub typów w przełączniku jako instrukcji case.

beatgammit
źródło