CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel) (01/06/91)
In article <11647@j.cc.purdue.edu>, zhou@brazil.psych.purdue.edu (Albert Zhou) wrote: >Here is the problem: > Suppose there is such a structure in the main part of the >program: > > repeat > statemetn 1 > statement 2 > . > . > . > statement n > until whatever > > Now I need to write a subroutine to point the program to statement >n. It seems there is no way to do it in turbo pascal, since goto >statement can not go out of a subroutine. Try reworking your repeat statement so that each statement 1..n has an associated value. Set that value in the subroutine(s). The loop would look something like: var flag_val : byte; ... flag_val := 0; repeat if flag_val <= 1 then statement1; if flag_val <= 2 then statement2; ... if flag_val <= n then statementn; flag_val := 0; until whatever; (Note that appropriate manipulation of flag_val allows statementI to cause a skip of a range of following statements I+1..n.) +--------------------------------------------------------------------+ | Karl Brendel Centers for Disease Control | | Internet: CDCKAB@EMUVM1.BITNET Epidemiology Program Office | | Bitnet: CDCKAB@EMUVM1 Atlanta, GA, USA | | Home of Epi Info 5.0 | +--------------------------------------------------------------------+
zhou@brazil.psych.purdue.edu (Albert Zhou) (01/06/91)
In article <25404@adm.brl.mil> CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel) writes: >In article <11647@j.cc.purdue.edu>, zhou@brazil.psych.purdue.edu > (Albert Zhou) wrote: > >Try reworking your repeat statement so that each statement 1..n has >an associated value. Set that value in the subroutine(s). The loop >would look something like: > >var > flag_val : byte; >... > flag_val := 0; > repeat > if flag_val <= 1 then statement1; > if flag_val <= 2 then statement2; > ... > if flag_val <= n then statementn; > flag_val := 0; > until whatever; > >(Note that appropriate manipulation of flag_val allows statementI to >cause a skip of a range of following statements I+1..n.) However, this only works when the error arises at the second level of the structure (suppose the repeat-until statement is at the first level). If the error arises at a deeper level, it will be a long way before going to statement n at the first level. Consider the following example: statement 2 calls proc1, procedure proc1; begin ... proc2; ... end; procedure proc2; begin ... proc3; ... end; procedure proc3; begin ... { this statement might cause error so I insert the error processing you suggested} if an error then begin val_flage = n; exit; end; ... end; So when the error comes up, it will continue to finish proc2 and proc1 before returning to the first level. But any attemp to continue the execution of proc2 and proc1 after an error arises will cause problem.
decomyn@penguin.uss.tek.com (01/07/91)
In article <11656@j.cc.purdue.edu> zhou@brazil.psych.purdue.edu (Albert Zhou) writes: >In article <25404@adm.brl.mil> CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel) writes: >>In article <11647@j.cc.purdue.edu>, zhou@brazil.psych.purdue.edu >> (Albert Zhou) wrote: >> >>Try reworking your repeat statement so that each statement 1..n has >>an associated value. Set that value in the subroutine(s). The loop >>would look something like: [code example deleted] > >However, this only works when the error arises at the second level of the >structure (suppose the repeat-until statement is at the first level). If >the error arises at a deeper level, it will be a long way before going to >statement n at the first level. Consider the following example: > > statement 2 calls proc1, > procedure proc1; > begin > ... > proc2; > ... > end; > > procedure proc2; > begin > ... > proc3; > ... > end; > > procedure proc3; > begin > ... > { this statement might cause error so I insert the error processing > you suggested} > if an error then begin > val_flage = n; > exit; > end; > ... > end; > > So when the error comes up, it will continue to finish proc2 and >proc1 before returning to the first level. But any attemp to continue the >execution of proc2 and proc1 after an error arises will cause problem. The solution is to test the value of val_flage after each call. In fact, if a procedure might be called from more than one statement, you can easily test for a change in the flag. Using your sample as a base, you could try: statement 2 calls proc1, procedure proc1; var Save_val : flage; { assumes type "flage" defined earlier } begin ... Save_val:=val_flage; proc2; if Save_Val<>val_flage then Exit ... end; procedure proc2; var Save_val : flage; { assumes type "flage" defined earlier } begin ... Save_val:=val_flage; proc3; if Save_Val<>val_flage then Exit ... end; procedure proc3; var begin ... { this statement might cause error so I insert the error processing you suggested} if an error then begin val_flage = n; exit; end; ... end; Clear enough? ------------------------------------------------------------------------------- Brendt Hess a.k.a. | Disclaimer: Opinions? I don't even work here! Vergil William de Comyn a.k.a. |----------------------------------------------- Payne Hirds | Life is not a zero-sum game: decomyn@penguin.uss.tek.com | don't treat it as such.
zhou@brazil.psych.purdue.edu (Albert Zhou) (01/07/91)
Any other solutions so far I've seen need quite a little extra work than if a direct goto statement can be implemented. Turbo Pascal doesn't have to disable cross-module goto to enforce "good programmin practice". Rather, it could let programmers to make choice, because under exceptional cases such goto's are the only best solutions. This reminds me of the suggestion made by some researchers to eliminate goto's altogether. Personally, I don't promote using goto's even within a block. Instead of using: repeat s1; s2; if c then goto out; s3; until forever; out:; I use: repeat s1; s2; s3; until c; However, in rare cases, s3 can be very time-consuming and by using the first code, one can save the time to execute s3 when c is true. My point is, let programmers to control their own programming style. And some "bad" practice can be the only good solution under exceptional case. Or a compiler directive (see G+) can be setup to enforce the rule of using goto directly. Just like range check.
CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel) (01/07/91)
In article <11656@j.cc.purdue.edu>, zhou@brazil.psych.purdue.edu (Albert Zhou) wrote: >In article <25404@adm.brl.mil> CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl > Brendel) writes: >>In article <11647@j.cc.purdue.edu>, zhou@brazil.psych.purdue.edu >> (Albert Zhou) wrote: >> >>Try reworking your repeat statement so that each statement 1..n has >>an associated value. Set that value in the subroutine(s). The loop >>would look something like: >> >>var >> flag_val : byte; >>... >> flag_val := 0; >> repeat >> if flag_val <= 1 then statement1; >> if flag_val <= 2 then statement2; >> ... >> if flag_val <= n then statementn; >> flag_val := 0; >> until whatever; >> >>(Note that appropriate manipulation of flag_val allows statementI to >>cause a skip of a range of following statements I+1..n.) > >However, this only works when the error arises at the second level of the >structure (suppose the repeat-until statement is at the first level). If [...remainder deleted...] Well, Albert, that isn't what your first posting asked about, although it apparently is what you _meant_ for it to ask about. Now you need a "long jump" capability, which you will find in a number of toolbox collections, including (of course) TurboPower's Turbo Professional and Object Professional. Your code would then look something like this: var ejr : JumpRecord; {global} flag_val : byte; {global} ... flag_val := 0; SetLongJump(ejr); repeat if flag_val <= 1 then statement1; if flag_val <= 2 then statement2; ... if flag_val <= n then statementn; flag_val := 0; until whatever; Then to return to the top of the loop, a routine would do LongJump(ejr);, setting flag_val as/if appropriate. (Note that ejr and flag_val need to be declared where they are visible to all appropriate units.) +--------------------------------------------------------------------+ | Karl Brendel Centers for Disease Control | | Internet: CDCKAB@EMUVM1.BITNET Epidemiology Program Office | | Bitnet: CDCKAB@EMUVM1 Atlanta, GA, USA | | Home of Epi Info 5.0 | +--------------------------------------------------------------------+
CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel) (01/09/91)
In article <11661@j.cc.purdue.edu>, zhou@brazil.psych.purdue.edu (Albert Zhou) wrote: >Any other solutions so far I've seen need quite a little extra work >than if a direct goto statement can be implemented. [...deleted...] >My point is, let programmers to control their own programming style. >And some "bad" practice can be the only good solution under >exceptional case. > >Or a compiler directive (see G+) can be setup to enforce the rule of >using goto directly. Just like range check. The "LongJump" solution takes no more work on the programmer's part (once the appropriate unit has been inserted into the USES statement) than your desired Goto would: To use a Goto, you must declare and use a label, then you must call the Goto as required; to use a LongJump, you must declare a JumpRecord, call SetLongJump, then call LongJump as required. (As in my second reply, I'm using Turbo Professional terminology here.) The fact of the matter is that a _pure_ Goto outside of a routine is not feasible in a language like Pascal. What happens to the stack frame of the routine you are going from? How is the stack frame created for the routine you are going to? And what happens to the stack frames of routines which were pending returns when you made the Goto? The LongJump approach deals with these matters by saving and restoring a specific stack frame. Even then, there are limitations (which don't affect your proposed use): you can jump from a lower stack frame to a higher one, but not vice versa. (I.e., you can jump "back", but not "forward".) Cheers-- +--------------------------------------------------------------------+ | Karl Brendel Centers for Disease Control | | Internet: CDCKAB@EMUVM1.BITNET Epidemiology Program Office | | Bitnet: CDCKAB@EMUVM1 Atlanta, GA, USA | | Home of Epi Info 5.0 | +--------------------------------------------------------------------+
dave@tygra.ddmi.com (David Conrad) (01/09/91)
In article <11661@j.cc.purdue.edu> zhou@brazil.psych.purdue.edu (Albert Zhou) writes: > >This reminds me of the suggestion made by some researchers to eliminate goto's >altogether. Personally, I don't promote using goto's even within a block. >Instead of using: > > repeat > s1; > s2; > if c then goto out; > s3; > until forever; > out:; > >I use: > repeat > s1; > s2; > s3; > until c; > >However, in rare cases, s3 can be very time-consuming and by using the first >code, one can save the time to execute s3 when c is true. > You could just use: repeat s1; s2; if not c then s3; until c; I've often seen it stated that there are situations where goto's are unavoidable, but I've never seen an instance of such a situation. Even finite state machines can be implemented by case statements, although if the case statements evaluate to nested if's instead of a jump table then I can see where one would rather use goto's to emulate the jump table. Or, with procedural types (call by name), you could actually code a jump table in an array. -- David R. Conrad dave@tygra.ddmi.com -- = CAT-TALK Conferencing Network, Computer Conferencing and File Archive = - 1-313-343-0800, 300/1200/2400/9600 baud, 8/N/1. New users use 'new' - = as a login id. AVAILABLE VIA PC-PURSUIT!!! (City code "MIDET") = E-MAIL Address: dave@DDMI.COM
bobb@vice.ICO.TEK.COM (Bob Beauchaine) (01/10/91)
In article <11661@j.cc.purdue.edu> zhou@brazil.psych.purdue.edu (Albert Zhou) writes: >I use: > repeat > s1; > s2; > s3; > until c; > >However, in rare cases, s3 can be very time-consuming and by using the first >code, one can save the time to execute s3 when c is true. > Seems reasonably straight forward to use this construct to avoid a potentially time consuming routine: repeat s1; s2; if not c then s3; until c; Bob Beauchaine bobb@vice.ICO.TEK.COM
mcastle@mcs213f.cs.umr.edu (Mike Castle (Nexus)) (01/10/91)
In article <6622@vice.ICO.TEK.COM> bobb@vice.ICO.TEK.COM (Bob Beauchaine) writes: >In article <11661@j.cc.purdue.edu> zhou@brazil.psych.purdue.edu (Albert Zhou) writes: >>I use: >> repeat >> s1; >> s2; >> s3; >> until c; >> >>[stuff deleted] > repeat > s1; > s2; > if not c then s3; > until c; My favorite is: Procedure DoSomeThing(var parms:etc); Var Ch := Char; Begin While True do Begin : Input data; : echo data and verify with y/n/q options if ch='q' then Exit; (* jump from procedure. *) if ch='y' then Begin : process data : process more data? (y/n); if ch='n' then Exit; End; End; End; (* DoSomeThing *) I assume this is really bad practice, but I like it. :-> -- Mike Castle (Nexus) S087891@UMRVMA.UMR.EDU (preferred) | ERROR: Invalid mcastle@mcs213k.cs.umr.edu (unix mail-YEACH!)| command 'HELP' Life is like a clock: You can work constantly, and be right | try 'HELP' all the time, or not work at all, and be right twice a day. |
einstein@cs.mcgill.ca (Michael CHOWET) (01/10/91)
In article <11661@j.cc.purdue.edu> you write: >Any other solutions so far I've seen need quite a little extra work than if >a direct goto statement can be implemented. Turbo Pascal doesn't have to >disable cross-module goto to enforce "good programmin practice". Rather, it >could let programmers to make choice, because under exceptional cases such >goto's are the only best solutions. Well, not to flame or anything, but my background was kept "GOTO-free". I was educated (and still am) in the spirit of "good programming" (whatever *that* may be :-). And even when going through the Pascal manual I found the GOTO statement, I didn't even bother looking at how to do this. All I saw was a statement that was a throwback to my BASIC days on an Apple ][+, an Atari 400, or worse on our Commodore VIC-20. >This reminds me of the suggestion made by some researchers to eliminate goto's >altogether. Personally, I don't promote using goto's even within a block. I must say I wholeheartedly agree. Although you contend that sometimes goto statements are the best alternative, I have done some rather vast projects, and I have yet to encounter the need for a goto statement. Goto's can be looked at as perhaps (again, don't take offense) a lazy person's cop out. Rather than sitting own with paper and pencil to map out the logical flow of the program, one does what one feels, then adds a goto to fill in the holes... I *would* like to see these statements eliminated. >Instead of using: > > repeat > s1; > s2; > if c then goto out; > s3; > until forever; > out:; > >I use: > repeat > s1; > s2; > s3; > until c; > >However, in rare cases, s3 can be very time-consuming and by using the first >code, one can save the time to execute s3 when c is true. If indeed this is the case, have you ever thought of the following: repeat s1; s2; if not c then s3 ; until c ; >My point is, let programmers to control their own programming style. And some >"bad" practice can be the only good solution under exceptional case. Well, I *don't* think one's programming practices should be dictated by the compiler, but rather create different compilers conforming to different programming styles, and allow the programmer the choice of languages. And one should adhere to the style dictated by the compiler chosen. ============================================================================== Today's message was brought to you by the letter 'S', the number 6, and =====> Einstein@cs.mcgill.ca <==== =====> Mike CHOWET | McGill CSUS VP External <===== Post back soon, now y'hear... ==============================================================================