On 23 Jul 2013 14:51, Dan Kimmel wrote:
Still, I like the concept. It'd be a way to get out of a block of
code without a GOTO. The Do .. EndDo marks the block of code. Are
there other ways to jump out of a block in CL structured op codes?
I agree with the desirability for the ability to use LEAVE in a
non-looping DO group. I was merely pointing out the restriction, as
diagnosed in messages; having totally overlooked referring to the help
text for the LEAVE command to find it even more clearly documented :-(
as was pointed out by Scott.
While I am not particularly fond of the GOTO, I am willing to use
them when they are useful and not overly fraught with potential
difficulties [likely to be seen only with later modifications to the
code]. The use of Monitor Message (MONMSG) versus use of feedback from
a function call, I think makes the use of the GOTO more
preferable\easier than some might prefer, if having /well-structured/
code [or otherwise described as code that is free of GOTOs] is
desirable. And in this case [overlooking the fact that the original
code seems easily modified instead, to just remove the redundancy] the
code could probably somewhat safely be written using a GOTO, by having a
LABEL established for the EndDo:
Do
chkobj ...
monmsg cpf9800 exec(goto err9800)
call ...
...
err9800: /* this label must remain with the EndDo */ +
EndDo
That is of course effectively the same as the LEAVE. The biggest
problems for maintenance are the possibility of someone copying the line
with the GOTO elsewhere, or adding a line before the EndDo such that the
label becomes associated with that new line of code. Copying the
Do-group somewhere else is not an issue; that will be diagnosed as a
duplicate label, and hopefully piquing the curiosity of the coder to
review all references. Moving the label in front of the EndDo to avoid
the line continuation is an option to avoid an inserted line, but that
may pose stylistic concerns [for aligning the Do\EndDo].
To eliminate the GOTO, the code might best maintain an effective
error indicator, much like how use of a function invocation might have
one naturally coding that way. In effect, making the code respond to
return-codes versus messaging. Consider the following two CLP samples
whereby the first changes to move the processing of CHKOBJ to a function
call, and the second continues to use MONMSG after the inline CHKOBJ,
but both change to eliminate the GOTO and use conditional logic based on
an effective indicator:
dcl &Authorized *char 01 /* I think *LGL not allowed as RtnVal */
,,.
Do
callprc ChkForObj parm(...) RTNVAL(&Authorized)
/* effectively: chgvar &Authorized value( ChkForObj(...) ) */
If cond(&Authorized *eq '1') then(Do)
call ...
...
EndDo
EndDo
dcl &SkipCall *lgl
,,.
Do
chkobj ...
monmsg cpf9800 exec(chgvar &SkipCall '1')
If cond(*not &SkipCall) then(Do)
call ...
...
EndDo
EndDo
FWiW I think the restriction might exist in part, because all of the
iterative control statements and the ITERATE itself were all going in
together. All of the code for LEAVE and ITERATE would be specific to
only new CLP sources; i.e. none of DOWHILE, DOFOR, or DOUNTIL existed
before. Testing for non-looping Do-groups is limited to the compiler vs
run-time; i.e. ensuring the compiler diagnosed them as errors, thus
limiting the amount of testing. Additionally it could have arisen in
part as a side effect from the difficulty of establishing an unambiguous
CMDLBL(*CURRENT) for the LEAVE. While obvious with regard to DO groups
that are standalone, most Do-groups are instead embedded in an IF\ELSE.
Like a GOTO LabelName can easily cause problems when code is changed
or copied, so too could a LEAVE in an IF, given an ELSE was added; i.e.
previously having processing continued in the implied ELSE, after adding
an ELSE the processing LEAVE likely would have been defined to continue
after the DO groups of both the IF and the ELSE.? The question mark,
because arguably [and documented as such, that] they are two distinct
non-nested Do-groups; one as part of the THEN of the IF statement and
the other as part of the ELSE which is its own separate statement. Thus
there is a possibly valid argument that the LEAVE CMDLBL(*CURRENT) would
properly go to the ELSE. If the CMDLBL() specification could extend to
a LABEL for an IF versus a LABEL for a DO statement, and all of the
DO\ENDDO under that IF were considered as one Do-group, then that could
make a LEAVE in a non-looping Do-group seem somewhat reasonable [to me].
Regards, Chuck
As an Amazon Associate we earn from qualifying purchases.