jim@umcp-cs.UUCP (Jim Williams) (05/03/86)
While discussing various features and miss-features of C with my friend Charley (mangoe) Wingate recently, we both agreed that the fall through case statement is among the least defensible of C's features. I submit the program below as the best use I have ever found for this feature. --------------- CUT HERE ------------ /* * xmas.c - a program to print The Twelve Days of Christmas * using the C fall thru case statement. * If this wasn't my idea, I appologize to whomever I * got the idea from, but I wrote the program 5 years * ago and I don't remember now. * * Jim Williams, jim@maryland, 2 May 1986 */ /* * If you have an ANSI compatible terminal then * #define ANSITTY. It makes the five Golden rings * especially tacky. */ #define ANSITTY #include <stdio.h> char *day_name[] = { "", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth" }; main() { int day; printf("The Twelve Days of Christmas.\n\n"); for (day=1; day<=12; day++) { printf("On the %s day of Christmas, my true love gave to me\n", day_name[day]); switch (day) { case 12: printf("\tTwelve drummers drumming,\n"); case 11: printf("\tEleven lords a leaping,\n"); case 10: printf("\tTen ladies dancing,\n"); case 9: printf("\tNine pipers piping,\n"); case 8: printf("\tEight maids a milking,\n"); case 7: printf("\tSeven swans a swimming,\n"); case 6: printf("\tSix geese a laying,\n"); case 5: #ifdef ANSITTY printf("\tFive [1;5;7mGolden[0m rings,\n"); #else printf("\tFive Golden rings,\n"); #endif case 4: printf("\tFour calling birds,\n"); case 3: printf("\tThree French hens,\n"); case 2: printf("\tTwo turtle doves, and\n"); case 1: printf("\tA partridge in a pear tree.\n\n"); } } } -- Jim \/\/illiams jim@mimsy.umd.edu umcp-cs!jim.UUCP
barmar@mit-eddie.MIT.EDU (Barry Margolin) (05/04/86)
In article <1298@umcp-cs.UUCP> jim@umcp-cs.UUCP (Jim Williams) writes: >... the fall through case statement is among the least >defensible of C's features. The only defense I can think of it is that it is more easily transformed into the non-fall-thru version than the other way around. All you have to do is add lots of "break" statements. If you want the effect of the fall-thru style in a language that only executes one case, you must either duplicate code or use lots of gotos in many cases. Note that this would not be so for your "12 Days of Christmas" program, because it could easily be implemented as a for loop that invoked each appropriate case in turn. But in the cases where the alternatives are not indexed so nicely it would not work. However, I agree with you that it is not really a necesary feature. -- Barry Margolin ARPA: barmar@MIT-Multics UUCP: ..!genrad!mit-eddie!barmar
root@icst-cmr (UNIX 4.2 BSD) (05/04/86)
While discussing various features and miss-features of C with my friend Charley (mangoe) Wingate recently, we both agreed that the fall through case statement is among the least defensible of C's features. Jim \/\/illiams jim@mimsy.umd.edu umcp-cs!jim.UUCP You will find much disagreement on that point, I'm afraid. Fall thru is more flexible. You can always break, but often cases are related so that a particular case requires a superset of another case. It is to DMR's credit that he realized this feature. I sure wouldn't have thought of it. (Root Boy) Jim Cottrell <rbj@cmr> "One man gathers what another man spills"
kwh@bentley.UUCP (KW Heuer) (05/09/86)
In article <528@brl-smoke.ARPA> root@icst-cmr ((Root Boy) Jim Cottrell) writes: [concerning the fall-through case feature] >You will find much disagreement on that point, I'm afraid. Fall thru is >more flexible. You can always break, but often cases are related so that >a particular case requires a superset of another case. It is to DMR's >credit that he realized this feature. I sure wouldn't have thought of it. An alternate implementation would have been for cases to be distinct by default, but "continue" at the bottom of a case would cause a fall-thru. (In this model, "break" would be meaningless inside a switch and "continue" would be meaningful, instead of the opposite.) Given that most use of the switch statement *does* have distinct cases, and the exceptions are often explicitly labeled /* no break */, I think this would've been better. (I would *almost* accept a model with automatic break and no keyword for fall-thru, and suffer the occasional goto.) One special instance is where the superset is actually an equivalence, i.e. two or more labels on the same code: case ' ': case '\t': case '\n': white(); break; This would be ugly with the auto-break model, but the solution is to allow case ' ','\t','\n': white(); which I think looks neater anyway. (Btw, I find case '0': ... case '9': digit(); annoyingly verbose in the current model, and often use "if" rather than "switch" because of it.) Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint
emjej@uokvax.UUCP (05/09/86)
/* Written 10:49 am May 4, 1986 by root@icst-cmr in net.lang.c */ You will find much disagreement on that point, I'm afraid. Fall thru is more flexible. You can always break, but often cases are related so that a particular case requires a superset of another case. It is to DMR's credit that he realized this feature. I sure wouldn't have thought of it. /* End of text from net.lang.c */ Ravening C worship should not get in the way of historical accuracy. The fall-through of cases in switch statements was inherited from BCPL. You have its originators to, uh, thank for it. James Jones
zap@duvan.UUCP (Svante Lindahl) (05/10/86)
In article <1298@umcp-cs.UUCP> jim@umcp-cs.UUCP writes: >/* > * xmas.c - a program to print The Twelve Days of Christmas > * using the C fall thru case statement. > * If this wasn't my idea, I appologize to whomever I > * got the idea from, but I wrote the program 5 years > * ago and I don't remember now. [...] Sorry this isnt' C, but I can't resist posting this... though I realize this is probably not a very apropriate newsgroup. It isn't my work, but I've lost track of who wrote it. Anyway it is an amusing piece of Algol-68-code. Example of execution under the TOPS-10 OS included after the code. BEGIN PROC readint = INT: (INT i; read(i); i); INT one=1, two=2, three=3, four=4, five=5, six=6, seven=7, eight=8, nine=9, ten=10, eleven=11, twelve=12; INT a=one; PRIO ME=5, LOVE=7, MY=7, LORDS=7, LADIES=7, PIPERS=7, DRUMMERS=7, MAIDS=7, SWANS=7, GEESE=7, GOLD=7, COLLY=7, FRENCH=7, TURTLE=7, PARTRIDGE=6; BOOL sent to=TRUE; OP THE = (BOOL a)BOOL:a, TWELFTH = (INT a)BOOL: a=twelve, ELEVENTH = (INT a)BOOL: a=eleven, TENTH = (INT a)BOOL: a=ten, NINTH = (INT a)BOOL: a=nine, EIGHTH = (INT a)BOOL: a=eight, SEVENTH = (INT a)BOOL: a=seven, SIXTH = (INT a)BOOL: a=six, FIFTH = (INT a)BOOL: a=five, FOURTH = (INT a)BOOL: a=four, THIRD = (INT a)BOOL: a=three, SECOND = (INT a)BOOL: a=two, FIRST = (INT a)BOOL: a=one; OP ME = (BOOL a, INT b)VOID: (IF a THEN print(b) FI), LOVE = (BOOL a, b)BOOL: (IF a THEN b ELSE FALSE FI), MY = (BOOL a, b)BOOL: a LOVE b, AND = (INT a)INT: a; MODE DATE = STRUCT(INT day, month); DATE christmas := (25, 12); OP LORDS = (INT a, b)INT: a*b, LADIES = (INT a, b)INT: a*b, PIPERS = (INT a, b)INT: a*b, DRUMMERS = (INT a, b)INT: a*b, MAIDS = (INT a, b)INT: a*b, SWANS = (INT a, b)INT: a*b, GEESE = (INT a, b)INT: a*b, GOLD = (INT a, b)INT: a*b, COLLY = (INT a, b)INT: a*b, FRENCH = (INT a, b)INT: a*b, TURTLE = (INT a, b)INT: a*b; OP LEAPING = (INT a)INT: a, DANCING = (INT a)INT: a, PIPING = (INT a)INT: a, DRUMMING = (INT a)INT: a, MILKING = (INT a)INT: a, SWIMMING = (INT a)INT: a, LAYING = (INT a)INT: a, RINGS = (INT a)INT: a, BIRDS = (INT a)INT: a, HENS = (INT a)INT: a, DOVES = (INT a)INT: a; OP PARTRIDGE = (INT a, b)INT: a+b; INT in a pear tree = 0; print("Factorial of "); print(day OF christmas := readint); print(" is "); IF day OF christmas > 12 THEN print("too big for this program."); stop FI; # Now we are ready.. # THE FIRST day OF christmas MY TRUE LOVE sent to ME a PARTRIDGE in a pear tree; THE SECOND day OF christmas MY TRUE LOVE sent to ME two TURTLE DOVES AND a PARTRIDGE in a pear tree; THE THIRD day OF christmas MY TRUE LOVE sent to ME three FRENCH HENS two TURTLE DOVES AND a PARTRIDGE in a pear tree; THE FOURTH day OF christmas MY TRUE LOVE sent to ME four COLLY BIRDS three FRENCH HENS two TURTLE DOVES AND a PARTRIDGE in a pear tree; THE FIFTH day OF christmas MY TRUE LOVE sent to ME five GOLD RINGS four COLLY BIRDS three FRENCH HENS two TURTLE DOVES AND a PARTRIDGE in a pear tree; THE SIXTH day OF christmas MY TRUE LOVE sent to ME six GEESE LAYING five GOLD RINGS four COLLY BIRDS three FRENCH HENS two TURTLE DOVES AND a PARTRIDGE in a pear tree; THE SEVENTH day OF christmas MY TRUE LOVE sent to ME seven SWANS SWIMMING six GEESE LAYING five GOLD RINGS four COLLY BIRDS three FRENCH HENS two TURTLE DOVES AND a PARTRIDGE in a pear tree; THE EIGHTH day OF christmas MY TRUE LOVE sent to ME eight MAIDS MILKING seven SWANS SWIMMING six GEESE LAYING five GOLD RINGS four COLLY BIRDS three FRENCH HENS two TURTLE DOVES AND a PARTRIDGE in a pear tree; THE NINTH day OF christmas MY TRUE LOVE sent to ME nine DRUMMERS DRUMMING eight MAIDS MILKING seven SWANS SWIMMING six GEESE LAYING five GOLD RINGS four COLLY BIRDS three FRENCH HENS two TURTLE DOVES AND a PARTRIDGE in a pear tree; THE TENTH day OF christmas MY TRUE LOVE sent to ME ten PIPERS PIPING nine DRUMMERS DRUMMING eight MAIDS MILKING seven SWANS SWIMMING six GEESE LAYING five GOLD RINGS four COLLY BIRDS three FRENCH HENS two TURTLE DOVES AND a PARTRIDGE in a pear tree; THE ELEVENTH day OF christmas MY TRUE LOVE sent to ME eleven LADIES DANCING ten PIPERS PIPING nine DRUMMERS DRUMMING eight MAIDS MILKING seven SWANS SWIMMING six GEESE LAYING five GOLD RINGS four COLLY BIRDS three FRENCH HENS two TURTLE DOVES AND a PARTRIDGE in a pear tree; THE TWELFTH day OF christmas MY TRUE LOVE sent to ME twelve LORDS LEAPING eleven LADIES DANCING ten PIPERS PIPING nine DRUMMERS DRUMMING eight MAIDS MILKING seven SWANS SWIMMING six GEESE LAYING five GOLD RINGS four COLLY BIRDS three FRENCH HENS two TURTLE DOVES AND a PARTRIDGE in a pear tree END .execut xmas A68: XMAS ALGOL68C Release 1.271 Unused space 991 Code generated 8r2271 LINK: Loading [LNKXCT A68 execution] 7 Factorial of +7 is +5040 Svante Lindahl, NADA, KTH Numerical Analysis & Computer Science UUCP: {seismo,mcvax}!enea!ttds!zap Royal Institute of Technology, Sweden ARPA: enea!ttds!zap@seismo.CSS.GOV EAN: zap@cs.kth.sunet
aglew@ccvaxa.UUCP (05/10/86)
>/* Written 10:49 am May 4, 1986 by root@icst-cmr in net.lang.c */ >You will find much disagreement on that point, I'm afraid. Fall thru is >more flexible. You can always break, but often cases are related so that >a particular case requires a superset of another case. It is to DMR's >credit that he realized this feature. I sure wouldn't have thought of it. >/* End of text from net.lang.c */ And what do you do if you have more than one case which is a superset of another? Eg. case A case B \ / \ / case C | | break Dup code or use gotos. The worst is when people use combinations of gotos and fall-through: case A: ... goto case_C; case B: ... /* fall through */ case C: case_C: ... break; There should be one way to do things. Special case constructs should only be used if they crop up frequently. I don't think fall through qualifies. Andy "Krazy" Glew. Gould CSD-Urbana. USEnet: ihnp4!uiucdcs!ccvaxa!aglew 1101 E. University, Urbana, IL 61801 ARPAnet: aglew@gswd-vms
rbj@icst-cmr (Root Boy Jim) (05/13/86)
> root@icst-cmr ((Root Boy) Jim Cottrell) writes: > [concerning the fall-through case feature] > >You will find much disagreement on that point, I'm afraid. Fall thru is > >more flexible. You can always break, but often cases are related so that > >a particular case requires a superset of another case. It is to DMR's > >credit that he realized this feature. I sure wouldn't have thought of it. > > An alternate implementation would have been for cases to be distinct by > default, but "continue" at the bottom of a case would cause a fall-thru. > (In this model, "break" would be meaningless inside a switch and "continue" > would be meaningful, instead of the opposite.) Interesting. We would give up the ability to contine a loop from within a switch, but gain the abilty to break from one. This might be a win. > Given that most use of the > switch statement *does* have distinct cases, and the exceptions are often > explicitly labeled /* no break */, I think this would've been better. > (I would *almost* accept a model with automatic break and no keyword for > fall-thru, and suffer the occasional goto.) The point I was trying to make is that given two alternatives, the one that can simulate the other is more powerful. One could lose this benefit by being to complex or abstruse, but that is another story. Note that assuming absence of a feature (break) is easier to generate code for (and get around from a programming point of view) than assuming presence of same. > One special instance is where the superset is actually an equivalence, i.e. > two or more labels on the same code: > case ' ': > case '\t': > case '\n': > white(); > break; Which occurs quite often. > This would be ugly with the auto-break model, but the solution is to allow > case ' ','\t','\n': > white(); > which I think looks neater anyway. I like it too. Other neat things use this convention. Some bad ones do too. > (Btw, I find > case '0': > ... > case '9': > digit(); > annoyingly verbose in the current model, and often use "if" rather than > "switch" because of it.) Or you could use `isdigit'. Or make up a table (say for ascii char syntax attributes) bitwise encoded, natch! > Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint (Root Boy) Jim Cottrell <rbj@cmr> "One man gathers what another man spills"