Loren's example of a useful role for GO TO, viz. "do P if X is not in
the set S", wherein S is represented by a list or a sequence of array
elements, is exactly the reason I have been asking, since about 1986,
to have two things: A block construct that doesn't do anything other
than provide a place for a construct label, and allowing the label on
EXIT to be on any kind of construct, not only a DO construct. For
compatibility, an EXIT statement with no construct label would still
refer to the most closely containing DO construct, not the most
closely containing construct even if it's not a DO construct.
I exdent my EXITs to the level of the block they refer to, in order to
expose the control flow more clearly. With a "block" and an EXIT that
can refer to it, and my indenting/exdenting style, Loren's example
would become:
outer: block ! or whatever spelling is most agreeable
inner: do i = 1, list_length
if ( list(i) == search_key ) then
! Update
exit outer
else if ( list(i) > search_key ) then
! Need to insert
exit inner
else
! continue searching
end if
end do inner
! Need to insert
! Do the insert
end block outer
For several years, I used a preprocessor that included a pretty-printer
(back before windowing systems, when listings were important). It included
a block that had no purpose other than as a place for a constuct label,
and allowed EXIT to refer to any construct label. From that preprocessor,
the output of the above would have been:
outer: block ! or whatever spelling is most agreeable
inner: do i = 1, list_length
| | if ( list(i) == search_key ) then
| | | ! Update
<--------exit outer
| | else if ( list(i) > search_key ) then
| | | ! Need to insert
| <-----exit inner
| | else
| | | ! continue searching
| | end if
| end do inner
| ! Need to insert
| ! Do the insert
end block outer
(Except that "block" was spelled "do block," "do" was spelled "do for"
and "end do" was spelled "end for" in that preprocessor.)
The control flow is quite clear in the pretty-printed form.
I would be tempted to reorganize the tests so that the low-probability
events (update or insert) aren't tested if the high-probability event
(the interesting place hasn't been reached) occurs:
outer: block
inner: do i = 1, list_length
| |<-if ( list(i) < search_key ) cycle inner
| | if ( list(i) == search_key ) then
| | | ! Update
<--------exit outer
| | end if
| | ! Need to insert
| <--exit inner
| end do inner
| ! Need to insert
| ! Do the insert
end block outer
In a future extension of Fortran, a "block" could also be used to enclose
a scoping unit. (I don't like "begin" because the natural end for it, in
the Fortran context is "end begin" [uff da!], not "end".)
Best regards,
Van Snyder
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|