Discussion:
"break" (was: Someone just too smart ...?)
Add Reply
Paul Gilmartin
2017-08-04 18:13:37 UTC
Reply
Permalink
Raw Message
Charles. PL/1 and REXX are about the same The break would be a goto
Rexx has no GOTO. "break" is LEAVE [control-variable] (and "continue is
ITERATE [control-variable]). I never use Rexx SIGNAL other than to force
an error; its side effects are dreadful.

Rexx sorely lacks "longjump".
switch = 1;
break? /* what is the PL/I to exit from a loop? */ ;
-- gil

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Smith III, Phil , HPE Data Security Voltage
2017-08-04 23:18:06 UTC
Reply
Permalink
Raw Message
Post by Paul Gilmartin
Rexx has no GOTO. "break" is LEAVE [control-variable] (and "continue is
ITERATE [control-variable]). I never use Rexx SIGNAL other than to force
an error; its side effects are dreadful.
By "to force an error", do you mean "to say that something bad happened and end the program"? Because if so, I agree 100% (well, except for the slightly perverse "calculated goto" via "SIGNAL VALUE", which is useful in *very* specific, rare, heavily documented instances).

That is, I find this code much easier to read and maintain:

do <someloopcondition>
...
if <statetest1 fails> signal BadCase1
...
if <statetest2 fails> signal BadCase2
...
end
...
* And way down below somewhere:
BadCase1:
say "The very bad case#1 happened!"
exit 1

BadCase2:
say "The very bad case#2 happened!"
exit 2
(etc.)

than:
do <someloopcondition>
...
maybeError=1
if <statetest1 fails> leave
...
maybeError=2
if <statetest2 fails> signal BadCase2
...
maybeError=0
end
if maybeError <> 0 then ...

or, perhaps more common:
do <someloopcondition>
...
if <statetest1 fails> then do
<handle the error, EXIT, etc.--often many lines>
end
...
if <statetest2 fails> then do
<handle the error, EXIT, etc.--often many lines >
end
...
end

The point is that the second and third cases are much harder to read and maintain. If you're disciplined about only using SIGNAL for this purpose, then seeing "Ah, he SIGNALs somewhere, he's done, that's not the mainline path" is quick and easy, allowing analysis of the mainline (and not incidentally grouping the errors in one place).

I don't want to get into a theological argument on a Friday afternoon, but having grown up with PL/I, the "No GOTOs noway never nohow" has always seemed overly rigid. Plus I'm currently living with code that uses the second technique above, and it's hell to debug (ok, in this case, it's much worse because it tends to set the maybeError *once* and then test five things, so you have to try to figure out which of the five really caused the error...just lazy programming).

...phsiii

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
David Crayford
2017-08-05 07:37:32 UTC
Reply
Permalink
Raw Message
Post by Smith III, Phil , HPE Data Security Voltage
Post by Paul Gilmartin
Rexx has no GOTO. "break" is LEAVE [control-variable] (and "continue is
ITERATE [control-variable]). I never use Rexx SIGNAL other than to force
an error; its side effects are dreadful.
By "to force an error", do you mean "to say that something bad happened and end the program"? Because if so, I agree 100% (well, except for the slightly perverse "calculated goto" via "SIGNAL VALUE", which is useful in *very* specific, rare, heavily documented instances).
do <someloopcondition>
...
if <statetest1 fails> signal BadCase1
...
if <statetest2 fails> signal BadCase2
...
end
...
say "The very bad case#1 happened!"
exit 1
say "The very bad case#2 happened!"
exit 2
(etc.)
That looks perfectly reasonable to me.
Post by Smith III, Phil , HPE Data Security Voltage
I don't want to get into a theological argument on a Friday afternoon, but having grown up with PL/I, the "No GOTOs noway never nohow" has always seemed overly rigid. Plus I'm currently living with code that uses the second technique above, and it's hell to debug (ok, in this case, it's much worse because it tends to set the maybeError *once* and then test five things, so you have to try to figure out which of the five really caused the error...just lazy programming).
The "goto is evil" debate is phony. A well placed goto can eliminate
duplicate code. I never use gotos these days purely because I program in
languages that have exceptions and finalization. In less sophisticated
languages error handling and object finalization is much simpler using
gotos. I've worked on projects that had coding standards prohibiting
the use of goto and the code quality was inferior.
Post by Smith III, Phil , HPE Data Security Voltage
...phsiii
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Bernd Oppolzer
2017-08-05 08:43:33 UTC
Reply
Permalink
Raw Message
A similar problem occurs, when I am coding a subroutine (or function)
in C, PL/1, Pascal, whatever, and I am checking some conditions at the
start and processing should stop if the conditions aren't true, but
immediate
return is no option, because some housekeeping has to be done at the end
of the function.

Example:

procedure do_something (parameters ...);

begin
do_initialization;
if not condition1 then
/* don't continue */
else
if not condition2 then
/* don't continue */
else
if not condition3 then
/* don't continue */
else
if not condition4 then
/* don't continue */
else
begin
do_processing
end;
do_housekeeping
end;

This looks awful because of the indentation.

For example, if implementing this logic in C, I could use goto,
of course. If I don't want to use goto, there is another solution,
involving a "dummy loop" and break:

void do_something (...)

{
do_initialization ();
do
{
/* one time dummy loop */

if (! condition1)
break;
/* don't continue */

if (! condition2)
break;
/* don't continue */

if (! condition3)
break;
/* don't continue */

if (! condition4)
break;
/* don't continue */

do_processing ();
}
while (0);

do_housekeeping ();
end;

This break, combined with the dummy loop,
works like a "goto forward", and IMO looks OK
and is maintainable.

In PL/1, you can use LEAVE for simple DO groups directly,
although you will get a warning, if you use it.

The warning is driven, AFAIK, by some improper use
(which occurs often in existing software), like:

DO I = 1 TO TABLE_COUNT;
IF TAB(I) = 0 THEN DO;
LEAVE;
END;
/* PROCESSING TAB (I) */
END;


often undected (LEAVE has no effect). Some companies
force the use of DO and END even on simple statements,
which leads to such errors. But that is (one or two)
another topics.

Kind regards

Bernd





Am 05.08.2017 um 01:19 schrieb Smith III, Phil (HPE Data Security
Post by Smith III, Phil , HPE Data Security Voltage
Post by Paul Gilmartin
Rexx has no GOTO. "break" is LEAVE [control-variable] (and "continue is
ITERATE [control-variable]). I never use Rexx SIGNAL other than to force
an error; its side effects are dreadful.
By "to force an error", do you mean "to say that something bad happened and end the program"? Because if so, I agree 100% (well, except for the slightly perverse "calculated goto" via "SIGNAL VALUE", which is useful in *very* specific, rare, heavily documented instances).
do <someloopcondition>
...
if <statetest1 fails> signal BadCase1
...
if <statetest2 fails> signal BadCase2
...
end
...
say "The very bad case#1 happened!"
exit 1
say "The very bad case#2 happened!"
exit 2
(etc.)
do <someloopcondition>
...
maybeError=1
if <statetest1 fails> leave
...
maybeError=2
if <statetest2 fails> signal BadCase2
...
maybeError=0
end
if maybeError <> 0 then ...
do <someloopcondition>
...
if <statetest1 fails> then do
<handle the error, EXIT, etc.--often many lines>
end
...
if <statetest2 fails> then do
<handle the error, EXIT, etc.--often many lines >
end
...
end
The point is that the second and third cases are much harder to read and maintain. If you're disciplined about only using SIGNAL for this purpose, then seeing "Ah, he SIGNALs somewhere, he's done, that's not the mainline path" is quick and easy, allowing analysis of the mainline (and not incidentally grouping the errors in one place).
I don't want to get into a theological argument on a Friday afternoon, but having grown up with PL/I, the "No GOTOs noway never nohow" has always seemed overly rigid. Plus I'm currently living with code that uses the second technique above, and it's hell to debug (ok, in this case, it's much worse because it tends to set the maybeError *once* and then test five things, so you have to try to figure out which of the five really caused the error...just lazy programming).
...phsiii
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Bernd Oppolzer
2017-08-05 08:45:29 UTC
Reply
Permalink
Raw Message
... some of the indentation in the first example,
which was already awful, has been further damaged
by my eMail program :-)
Post by Bernd Oppolzer
A similar problem occurs, when I am coding a subroutine (or function)
in C, PL/1, Pascal, whatever, and I am checking some conditions at the
start and processing should stop if the conditions aren't true, but
immediate
return is no option, because some housekeeping has to be done at the end
of the function.
procedure do_something (parameters ...);
begin
do_initialization;
if not condition1 then
/* don't continue */
else
if not condition2 then
/* don't continue */
else
if not condition3 then
/* don't continue */
else
if not condition4 then
/* don't continue */
else
begin
do_processing
end;
do_housekeeping
end;
This looks awful because of the indentation.
For example, if implementing this logic in C, I could use goto,
of course. If I don't want to use goto, there is another solution,
void do_something (...)
{
do_initialization ();
do
{
/* one time dummy loop */
if (! condition1)
break;
/* don't continue */
if (! condition2)
break;
/* don't continue */
if (! condition3)
break;
/* don't continue */
if (! condition4)
break;
/* don't continue */
do_processing ();
}
while (0);
do_housekeeping ();
end;
This break, combined with the dummy loop,
works like a "goto forward", and IMO looks OK
and is maintainable.
In PL/1, you can use LEAVE for simple DO groups directly,
although you will get a warning, if you use it.
The warning is driven, AFAIK, by some improper use
DO I = 1 TO TABLE_COUNT;
IF TAB(I) = 0 THEN DO;
LEAVE;
END;
/* PROCESSING TAB (I) */
END;
often undected (LEAVE has no effect). Some companies
force the use of DO and END even on simple statements,
which leads to such errors. But that is (one or two)
another topics.
Kind regards
Bernd
Am 05.08.2017 um 01:19 schrieb Smith III, Phil (HPE Data Security
Post by Smith III, Phil , HPE Data Security Voltage
Post by Paul Gilmartin
Rexx has no GOTO. "break" is LEAVE [control-variable] (and
"continue is
ITERATE [control-variable]). I never use Rexx SIGNAL other than to force
an error; its side effects are dreadful.
By "to force an error", do you mean "to say that something bad
happened and end the program"? Because if so, I agree 100% (well,
except for the slightly perverse "calculated goto" via "SIGNAL
VALUE", which is useful in *very* specific, rare, heavily documented
instances).
do <someloopcondition>
...
if <statetest1 fails> signal BadCase1
...
if <statetest2 fails> signal BadCase2
...
end
...
say "The very bad case#1 happened!"
exit 1
say "The very bad case#2 happened!"
exit 2
(etc.)
do <someloopcondition>
...
maybeError=1
if <statetest1 fails> leave
...
maybeError=2
if <statetest2 fails> signal BadCase2
...
maybeError=0
end
if maybeError <> 0 then ...
do <someloopcondition>
...
if <statetest1 fails> then do
<handle the error, EXIT, etc.--often many lines>
end
...
if <statetest2 fails> then do
<handle the error, EXIT, etc.--often many lines >
end
...
end
The point is that the second and third cases are much harder to read
and maintain. If you're disciplined about only using SIGNAL for this
purpose, then seeing "Ah, he SIGNALs somewhere, he's done, that's not
the mainline path" is quick and easy, allowing analysis of the
mainline (and not incidentally grouping the errors in one place).
I don't want to get into a theological argument on a Friday
afternoon, but having grown up with PL/I, the "No GOTOs noway never
nohow" has always seemed overly rigid. Plus I'm currently living with
code that uses the second technique above, and it's hell to debug
(ok, in this case, it's much worse because it tends to set the
maybeError *once* and then test five things, so you have to try to
figure out which of the five really caused the error...just lazy
programming).
...phsiii
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Robert Prins
2017-08-05 09:18:19 UTC
Reply
Permalink
Raw Message
.... some of the indentation in the first example,
which was already awful, has been further damaged
by my eMail program :-)
That's why PL/I has the "SELECT" statement:

do_something: proc;
do_initialization;

select;
when (not condition 1);
when (not condition 2);
when (not condition 3);
when (not condition 4);
other
do_processing
end;

do_housekeeping
end do_something;

Robert
Post by Bernd Oppolzer
A similar problem occurs, when I am coding a subroutine (or function)
in C, PL/1, Pascal, whatever, and I am checking some conditions at the
start and processing should stop if the conditions aren't true, but immediate
return is no option, because some housekeeping has to be done at the end
of the function.
procedure do_something (parameters ...);
begin
do_initialization;
if not condition1 then
/* don't continue */
else
if not condition2 then
/* don't continue */
else
if not condition3 then
/* don't continue */
else
if not condition4 then
/* don't continue */
else
begin
do_processing
end;
do_housekeeping
end;
This looks awful because of the indentation.
For example, if implementing this logic in C, I could use goto,
of course. If I don't want to use goto, there is another solution,
void do_something (...)
{
do_initialization ();
do
{
/* one time dummy loop */
if (! condition1)
break;
/* don't continue */
if (! condition2)
break;
/* don't continue */
if (! condition3)
break;
/* don't continue */
if (! condition4)
break;
/* don't continue */
do_processing ();
}
while (0);
do_housekeeping ();
end;
This break, combined with the dummy loop,
works like a "goto forward", and IMO looks OK
and is maintainable.
In PL/1, you can use LEAVE for simple DO groups directly,
although you will get a warning, if you use it.
The warning is driven, AFAIK, by some improper use
DO I = 1 TO TABLE_COUNT;
IF TAB(I) = 0 THEN DO;
LEAVE;
END;
/* PROCESSING TAB (I) */
END;
often undected (LEAVE has no effect). Some companies
force the use of DO and END even on simple statements,
which leads to such errors. But that is (one or two)
another topics.
--
Robert AH Prins
robert(a)prino(d)org

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Smith III, Phil , HPE Data Security Voltage
2017-08-06 01:48:24 UTC
Reply
Permalink
Raw Message
Post by Paul Gilmartin
A lot of that I'd do with SELECT and CALL. But partly I'm being compulsive about
avoiding SIGNAL. And sometimes I force a terminal condition (such as NOVALUE)
to get the procedure call trace.
(Continuing this Socratically, not really trying to convince anyone, but in fact hoping to maybe learn something)

Forcing the NOVALUE is appealing. And certainly if you have a ton of nesting, such that you need the traceback (that's not a put-down, some programs work that way!), SIGNAL would be destructive.

My large programs haven't tended to have this kind of structure, just because, well, they haven't. Some of my servers have been largish (10K++ lines), or massively iterative BUT call structure was predictable (nested Multipart/RFC822 MIME, for example, in a remailer-when that got too deep and blew the implementation limit, I didn't need to know where it had come from; the error handler would send me the offending note for analysis and manual processing). But I can certainly imagine cases where traceback would be useful!

See, I did learn something already...

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Paul Gilmartin
2017-08-04 23:38:30 UTC
Reply
Permalink
Raw Message
Post by Paul Gilmartin
Rexx has no GOTO. "break" is LEAVE [control-variable] (and "continue is
ITERATE [control-variable]). I never use Rexx SIGNAL other than to force
an error; its side effects are dreadful.
By "to force an error", do you mean "to say that something bad happened and end the program"? ...
I begin every Rexx program with SIGNAL ON NOVALUE but code no handler.
I consider reference to an undefined symbol a coding error, and fatal because
there's really no way to recover.
... Because if so, I agree 100% (well, except for the slightly perverse "calculated goto" via "SIGNAL VALUE", which is useful in *very* specific, rare, heavily documented instances).
do <someloopcondition>
...
if <statetest1 fails> signal BadCase1
...
if <statetest2 fails> signal BadCase2
...
end
...
A lot of that I'd do with SELECT and CALL. But partly I'm being compulsive about
avoiding SIGNAL. And sometimes I force a terminal condition (such as NOVALUE)
to get the procedure call trace.
say "The very bad case#1 happened!"
exit 1
say "The very bad case#2 happened!"
exit 2
(etc.)
do <someloopcondition>
...
maybeError=1
if <statetest1 fails> leave
...
maybeError=2
if <statetest2 fails> signal BadCase2
...
maybeError=0
end
if maybeError <> 0 then ...
do <someloopcondition>
...
if <statetest1 fails> then do
<handle the error, EXIT, etc.--often many lines>
end
...
if <statetest2 fails> then do
<handle the error, EXIT, etc.--often many lines >
end
...
end
The point is that the second and third cases are much harder to read and maintain. If you're disciplined about only using SIGNAL for this purpose, then seeing "Ah, he SIGNALs somewhere, he's done, that's not the mainline path" is quick and easy, allowing analysis of the mainline (and not incidentally grouping the errors in one place).
-- gil

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Paul Gilmartin
2017-08-05 14:29:34 UTC
Reply
Permalink
Raw Message
Post by Bernd Oppolzer
... some of the indentation in the first example,
which was already awful, has been further damaged
by my eMail program :-)
The original Subject: of this thread included the words "too smart". Alas,
that's characteristic of too many eMail programs. To me the major irritant
is inserting "[too] smart quotes", making copy-and-paste of code samples
impossible.
Post by Bernd Oppolzer
Post by Bernd Oppolzer
For example, if implementing this logic in C, I could use goto,
of course. If I don't want to use goto, there is another solution,
void do_something (...)
{
do_initialization ();
do
{
/* one time dummy loop */
if (! condition1)
break;
/* don't continue */
if (! condition2)
break;
/* don't continue */
if (! condition3)
break;
/* don't continue */
if (! condition4)
break;
/* don't continue */
do_processing ();
}
while (0);
do_housekeeping ();
end;
This break, combined with the dummy loop,
works like a "goto forward", and IMO looks OK
and is maintainable.
But isn't that merely:

do_initialization
if ( condition1 &&amp; condition2 &&amp; condition3 &&amp; condition4 ) {
do_processing; }
do_housekeeping
Post by Bernd Oppolzer
Post by Bernd Oppolzer
In PL/1, you can use LEAVE for simple DO groups directly,
although you will get a warning, if you use it.
The warning is driven, AFAIK, by some improper use
DO I = 1 TO TABLE_COUNT;
IF TAB(I) = 0 THEN DO;
LEAVE;
END;
/* PROCESSING TAB (I) */
END;
often undected (LEAVE has no effect). Some companies
In Rexx, ITERATE and LEAVE apply only to loops with control variables,
and naming the control variable on ITERATE, LEAVE, and END much improves
legibility. Often, I use dummy loops only to facilitate DO-END matching. I
consider it an implementation shortcoming that the interpreter fails to report
such mismatches when the DO is skipped by an IF.
Post by Bernd Oppolzer
Post by Bernd Oppolzer
force the use of DO and END even on simple statements,
which leads to such errors. But that is (one or two)
another topics.
I've seen that. It results in undesirably deep nesting, which impels
shallow indention, often a single space per level, especially with
fixed-80 input with line numbers.

I'm an enthusiast for strong closure: IF ... FI and DO ... DONE.

-- gil

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Paul Gilmartin
2017-08-05 15:00:42 UTC
Reply
Permalink
Raw Message
Post by Bernd Oppolzer
...
do_initialization
if ( condition1 &&amp; condition2 &&amp; condition3 &&amp; condition4 ) {
do_processing; }
do_housekeeping
Testing whether the eMail interface produces HTML less mangled than
the web interface I generally use:

But isn't that merely:

do_initialization
if ( condition1 && condition2 && condition3 && condition4 ) {
do_processing; }
do_housekeeping
Post by Bernd Oppolzer
In Rexx, ITERATE and LEAVE apply only to loops with control variables,
I'll correct myself after RTFM. ITERATE and LEAVE applly to both simple
repetitive loops (no control variable) and to controlled repetitive loops,
but not to simple (non-repetitive) do groups.
Post by Bernd Oppolzer
and naming the control variable on ITERATE, LEAVE, and END much improves
legibility. Often, I use dummy loops only to facilitate DO-END matching. I
consider it an implementation shortcoming that the interpreter fails to report
such mismatches when the DO is skipped by an IF.
-- gil

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to ***@listserv.ua.edu with the message: INFO IBM-MAIN
Gerard Schildberger
2017-08-05 19:14:59 UTC
Reply
Permalink
Raw Message
Post by Paul Gilmartin
Post by Bernd Oppolzer
... some of the indentation in the first example,
which was already awful, has been further damaged
by my eMail program :-)
The original Subject: of this thread included the words "too smart". Alas,
that's characteristic of too many eMail programs. To me the major irritant
is inserting "[too] smart quotes", making copy-and-paste of code samples
impossible.
Post by Bernd Oppolzer
Post by Bernd Oppolzer
For example, if implementing this logic in C, I could use goto,
of course. If I don't want to use goto, there is another solution,
void do_something (...)
{
do_initialization ();
do
{
/* one time dummy loop */
if (! condition1)
break;
/* don't continue */
if (! condition2)
break;
/* don't continue */
if (! condition3)
break;
/* don't continue */
if (! condition4)
break;
/* don't continue */
do_processing ();
}
while (0);
do_housekeeping ();
end;
This break, combined with the dummy loop,
works like a "goto forward", and IMO looks OK
and is maintainable.
do_initialization
if ( condition1 &&amp; condition2 &&amp; condition3 &&amp; condition4 ) {
do_processing; }
do_housekeeping
Post by Bernd Oppolzer
Post by Bernd Oppolzer
In PL/1, you can use LEAVE for simple DO groups directly,
although you will get a warning, if you use it.
The warning is driven, AFAIK, by some improper use
DO I = 1 TO TABLE_COUNT;
IF TAB(I) = 0 THEN DO;
LEAVE;
END;
/* PROCESSING TAB (I) */
END;
often undected (LEAVE has no effect). Some companies
In Rexx, ITERATE and LEAVE apply only to loops with control variables,
and naming the control variable on ITERATE, LEAVE, and END much improves
legibility. Often, I use dummy loops only to facilitate DO-END matching. I
consider it an implementation shortcoming that the interpreter fails to report
such mismatches when the DO is skipped by an IF.
No, that's not quite correct.

ITERATE and LEAVE instructions can also apply to DO loops with
no control variable, but which must contain some other control
structure(s) like WHILE, UNTIL, or FOREVER, or a repeater.
A very simple example of the later:

k=0
do 20
k=k+1
if k>5 then leave
end
________________________________________________ Gerard Schildberger
Post by Paul Gilmartin
Post by Bernd Oppolzer
Post by Bernd Oppolzer
force the use of DO and END even on simple statements,
which leads to such errors. But that is (one or two)
another topics.
I've seen that. It results in undesirably deep nesting, which impels
shallow indention, often a single space per level, especially with
fixed-80 input with line numbers.
I'm an enthusiast for strong closure: IF ... FI and DO ... DONE.
-- gil
Loading...