colonel@sunybcs.UUCP (Col. G. L. Sicherman) (07/18/86)
> So to get the effect equivalent to "zero" out of the null statement, do we > invent some sort of "positional notation" for statements?!?! Fine with me! I'd rather be able to write while ('\n' != getchar()) nothing; than while ('\n' != getchar()) /* do nothing */ ; -- Col. G. L. Sicherman UU: ...{rocksvax|decvax}!sunybcs!colonel CS: colonel@buffalo-cs BI: csdsicher@sunyabva
franka@mmintl.UUCP (Frank Adams) (07/22/86)
>> So to get the effect equivalent to "zero" out of the null statement, do we >> invent some sort of "positional notation" for statements?!?! I find the use of the word "invent" somewhat objectionable here. Perhaps you have heard of FORTRAN, the oldest high level language of them all?[1] Perhaps you have heard of the CONTINUE statement therein, which does nothing? I see nothing wrong with the idea of a an explicit null statement, but let's not pretend it's a new idea. Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Multimate International 52 Oakland Ave North E. Hartford, CT 06108 [1] I believe FORTRAN is somewhat older than either ALGOL or LISP, which are of the same general vintage. If I'm wrong, don't bother to correct me.
paulsc@orca.UUCP (Paul Scherf) (07/22/86)
In article <442@sunybcs.UUCP> colonel@sunybcs.UUCP (Col. G. L. Sicherman) writes: >> So to get the effect equivalent to "zero" out of the null statement, do we >> invent some sort of "positional notation" for statements?!?! > >Fine with me! I'd rather be able to write > > while ('\n' != getchar()) nothing; > >than > > while ('\n' != getchar()) /* do nothing */ ; You already can. Well, almost. while ('\n' != getchar()) continue; It works for do-while and for loops too. Paul Scherf, Tektronix, Box 1000, MS 61-028, Wilsonville, OR, USA tektronix!orca!paulsc
sbs@valid.UUCP (Steven Brian McKechnie Sargent) (07/23/86)
> > So to get the effect equivalent to "zero" out of the null statement, do we > > invent some sort of "positional notation" for statements?!?! > Fine with me! I'd rather be able to write > while ('\n' != getchar()) nothing; > than > while ('\n' != getchar()) /* do nothing */ ; > -- > Col. G. L. Sicherman > UU: ...{rocksvax|decvax}!sunybcs!colonel > CS: colonel@buffalo-cs > BI: csdsicher@sunyabva Only a barbarian or Obfuscated C Contest winner would champion the use of #define nothing /* do nothing */ but I figured I'd mention it anyway. I format null-body loops so: while (getchar() != '\n') ; which fixes most of the "eyeball ambiguity." The null statement problem is much worse in Pascal because there is no explicit statement termination, only separation. So 1 IF complicated predicate involving several dozen apparently randomly 2 selected expressions THEN 3 {Attempt to do nothing innocuously}; 4 ELSE BEGIN 5 writeln('Read the code to find out what happened here.'); 6 i := i/0; 7 END; is a lose, lose, lose. That ; character on line 3 makes Mr. Pascal very sick. You can replace it with the sequence BEGIN END, which looks a little stoopid but gets the job done. In Berkeley Pascal we had an explicit "null" statement that did what you want with no muss & no fuss: it worked anywhere that the sequence BEGIN ... END did. I sort of like the Modula-2 convention of tagging everything with an END. It makes programs chattier than they need to be but it seems to get the point across. Actually, the Algol/UNIX Shell convention of if...endif, do...done, case...esac is best of all, because you can read the code forwards OR backwards... S.
chris@umcp-cs.UUCP (Chris Torek) (07/23/86)
In article <484@valid.UUCP> sbs@valid.UUCP (Steven Brian McKechnie Sargent) writes: >Only a barbarian or Obfuscated C Contest winner would champion the use of > #define nothing /* do nothing */ >but I figured I'd mention it anyway. Actually, I came up with a use for something very like this recently. In C one can define a macro that `looks' like a function or procedure: /* successor function, mod 5 */ #define succ(i) (((i) + 1) % 5) In many cases the function is more complex: #define get_node() \ (freenodes ? \ (temp = freenodes, freenodes = freenodes->next, temp) : \ allocate_more_nodes()) If the macro is emulating a procedure, it need not even be an expression: #define proc(exp) \ if (exp) \ a(); \ else \ b() Note the lack of a semicolon. Instances of the macro include the semicolon, and it would not do to include it twice: v = e; proc(v); other(v); Sometimes, however, there is nothing to do in the `else' clause: #define SaveB(b) \ if ((b)->b_AfterGroupRst == NULL || \ (b)->b_AfterGroupRst->sv_level != CurrentGroup) \ DoSave(b); \ else \ /* do nothing */ This is fine in normal contexts: v = e; SaveB(v); other(v); However, now a missing semicolon can wreak silent havoc: v = e; SaveB(v) other(v); This expands to `if (v->b_...) DoSave(v); else other(v);'---not at all what was meant, but syntactically valid. One solution is to invert the `if': #define SaveB(b) \ if ((b)->b_AfterGroupRst != NULL && \ (b)->b_AfterGroupRst->sv_level == CurrentGroup) \ /* do nothing */ ; \ else \ DoSave(b) This is, however, confusing, at best. What is needed is an explicit `nothing'. In fact, this works: #define SaveB(b) \ if ((b)->b_AfterGroupRst == NULL || \ (b)->b_AfterGroupRst->sv_level != CurrentGroup) \ DoSave(b); \ else \ 0 since a constant is an expression, and an expression is a statement. This will make the case of the missing semicolon produce a syntax error. Unfortunately, it also makes `lint' complain (at least when used with `-h'). The solution below avoids both of these problems, but is hardly pretty: #ifdef lint #define do_nothing rand() #else #define do_nothing 0 #endif /* * Save a binding. */ #define SaveB(b) \ if ((b)->b_AfterGroupRst == NULL || \ (b)->b_AfterGroupRst->sv_level != CurrentGroup) \ DoSave(b); \ else \ do_nothing /* * Undo a save. */ #define UnSaveB(b) \ if ((b)->b_AfterGroupRst != NULL) \ DoUnsave(b); \ else \ do_nothing I think this also argues for an explicit `null statement'. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
sjoerd@botter.UUCP (sjoerd) (07/25/86)
In article <2565@umcp-cs.UUCP> chris@maryland.UUCP (Chris Torek) writes: [ About null statements in #defines ] >In many cases the function is more complex: > > #define SaveB(b) \ > if ((b)->b_AfterGroupRst == NULL || \ > (b)->b_AfterGroupRst->sv_level != CurrentGroup) \ > DoSave(b); \ > else \ > /* do nothing */ > And continues to suggest a few solutions since the above will wreak havoc if you forget a semicolon in the call. Another solution (which does not require a null statement) is: #define SaveB(b) \ (/* if */ ((b)->b_AfterGroupRst == NULL || \ (b)->b_AfterGroupRst->sv_level != CurrentGroup) /* then */ && \ DoSave(b)) I agree that this may be bit confusing, but this has the great advantage that you can use it everywhere where you can use an expression (like in a for statement). Another use for this construct is the assert macro: #define assert(e) (!(e) && printf("Assertion failed ...")) You can write this differently: #define assert(e) ((e) || printf("Assertion failed ...")) I like this much better than the if statement that is usually used. >In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) >UUCP: seismo!umcp-cs!chris >CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
greg@utcsri.UUCP (Gregory Smith) (07/29/86)
In article <484@valid.UUCP> sbs@valid.UUCP (Steven Brian McKechnie Sargent) writes: >> Fine with me! I'd rather be able to write >> while ('\n' != getchar()) nothing; >> than >> while ('\n' != getchar()) /* do nothing */ ; > >I format null-body loops so: > while (getchar() != '\n') > ; >which fixes most of the "eyeball ambiguity." > Good stuff, I plan to decide on one of these practices and follow it. C has a danger inherent in the do..while loop, some people indent them as below: do{ /* a whole lotta stuff, many lines */ } while( foo_bar(*x++) != BLETCH ); Thus making it look like the last line is a null-bodied 'while'. I ( like most ) circumvent this by writing }while(...) at the end, and making the body a compound statement whether it needs it or not ( A loose 'do' is *scary*.... could get lost in there... bolt it to a '{' ) >The null statement problem is much worse in Pascal because there is no >explicit statement termination, only separation. So > > 1 IF complicated predicate involving several dozen apparently randomly > 2 selected expressions THEN > 3 {Attempt to do nothing innocuously}; > 4 ELSE BEGIN > 5 writeln('Read the code to find out what happened here.'); > 6 i := i/0; > 7 END; > >is a lose, lose, lose. That ; character on line 3 makes Mr. Pascal very sick. >You can replace it with the sequence BEGIN END, which looks a little stoopid Isn't there a null statement ""? I.e., can't you say IF .... THEN ELSE BEGIN ... END ??? ( i.e. just delete the ; on line 3. Sorry, can't find a reference ). PS: a Pascal teaching compiler I once used could come up with the message 'semicolon is never legal before ELSE'. Neat, huh? -- "You'll need more than a Tylenol if you don't tell me where my father is!" - The Ice Pirates ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
sommar@enea.UUCP (Erland Sommarskog) (07/30/86)
In article <3188@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) writes: >Isn't there a null statement ""? I.e., can't you say > > IF .... THEN ELSE BEGIN ... END > >??? ( i.e. just delete the ; on line 3. Sorry, can't find a reference ). IF <expression> THEN ELSE <statement> is legal Pascal. Look e.g. in Wirth's report only book of Pascal that contains the syntax graphs. You can express it that in Pascal the empty statement is written with an empty string. >PS: a Pascal teaching compiler I once used could come up with the >message 'semicolon is never legal before ELSE'. Neat, huh? So does DEC's Pascal compiler for VMS: "; ELSE is not valid Pascal" But most compilers says ELSE ^6 And at the end of list explains: "Illegal symbol". It takes some until you react normally and directly start to look for an illegal semicolon.