Goto inside a call statement?

  • Follow


I encountered this (edited for readability) and when I tried to dump
the goto and change it to an If Then I got a "label 170 missing" error
pointing me to the call statement.  Included the sub's header in case
it is useful to someone.

      If (condition) Goto 170
      ...
      Call EWER(*170)
      ...
  170 ...


Subroutine EWER(*)

Can someone tell me what is going on here?
0
Reply saquisenberry (24) 2/26/2008 8:45:01 PM

"Shawn" <saquisenberry@gmail.com> wrote in message 
news:0b81e7b2-4103-42de-ae2f-c8a58c25fbba@d5g2000hsc.googlegroups.com...
>I encountered this (edited for readability) and when I tried to dump
> the goto and change it to an If Then I got a "label 170 missing" error
> pointing me to the call statement.  Included the sub's header in case
> it is useful to someone.
>
>      If (condition) Goto 170
>      ...
>      Call EWER(*170)
>      ...
>  170 ...
>
>
> Subroutine EWER(*)
>
> Can someone tell me what is going on here?

It is an alternate return ("Fortran 95/2003 Explained" App. B.1.9), an 
obsolescent feature. You will find that EWER contains a statement 'return 1' 
which, when executed, will transfer control to that statement whose label 
first appears in the actual arguments preceded by an *, to wit 170.

HTH

Mike Metcalf 


0
Reply michaelmetcalf (810) 2/26/2008 8:54:31 PM


> It is an alternate return ("Fortran 95/2003 Explained" App. B.1.9), an
> obsolescent feature. You will find that EWER contains a statement 'return 1'
> which, when executed, will transfer control to that statement whose label
> first appears in the actual arguments preceded by an *, to wit 170.

Indeed there is a "return 1" in the sub.  Can this be obsolete
reference be eliminated by changing the offending subroutine into a
function that returns either a 1 or 0 and having a conditional handle
that value returned?
0
Reply saquisenberry (24) 2/26/2008 9:04:33 PM

Shawn wrote:
>> It is an alternate return ("Fortran 95/2003 Explained" App. B.1.9), an
>> obsolescent feature. You will find that EWER contains a statement 'return 1'
>> which, when executed, will transfer control to that statement whose label
>> first appears in the actual arguments preceded by an *, to wit 170.
> 
> Indeed there is a "return 1" in the sub.  Can this be obsolete
> reference be eliminated by changing the offending subroutine into a
> function that returns either a 1 or 0 and having a conditional handle
> that value returned?
Yes, but it's not usually a good idea to convert subroutines into
function unless you are sure about how they work and how they
will be used (IMO).  A better approach is to replace the *
arguments by a variable and test it's value after the call.
        call ewer (switch)
        if (switch .eq. 1) go to 170

It's a little general and allows for more return values and for
subroutines that have more than one alternate return.

Dick Hendrickson
0
Reply dick.hendrickson (1286) 2/26/2008 9:11:40 PM

Thanks for the help guys.

Shawn
0
Reply saquisenberry (24) 2/26/2008 9:30:31 PM

Dick Hendrickson wrote:
> [...]  A better approach is to replace the *
> arguments by a variable and test it's value after the call.
>        call ewer (switch)
>        if (switch .eq. 1) go to 170
>
> It's a little general and allows for more return values and for
> subroutines that have more than one alternate return.

On the other hand, once you're familiar with the alternate
return feature, it's easier to read (and can often work faster
depending on the compiler).  If you have lots of code that
needs to be fault tolerant, the "obsolescent" alternate
return feature is the only kind of exception handling
feature Fortran has.

-- 
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies."   --  C. A. R. Hoare 


0
Reply jamesgiles (2210) 2/29/2008 4:19:40 AM

"James Giles" <jamesgiles@worldnet.att.net> writes:

> On the other hand, once you're familiar with the alternate
> return feature, it's easier to read (and can often work faster
> depending on the compiler).  If you have lots of code that
> needs to be fault tolerant, the "obsolescent" alternate
> return feature is the only kind of exception handling
> feature Fortran has.

I would advise against the alternate return facility from a software
engineering point of view because it is in violation of the "single
entry - single exit" directive. The simulation code I'm working with at
the moment has routines with three, four, even five alternate returns
which is a complete nightmare to read or extend (yes, the calling
routines are sprinkled with labels and GOTOs, there is no consistency in
label numbers, headaches galore).

If you use the alternate return with only one alternative in a
consistent manner, e.g. as a means to jump to a (consistently numbered)
label for error handling, cleanup and the like, I don't think it's a bad
idea as such - but a returned error code is in my opinion preferable.


Sebastian
0
Reply hanigk (201) 2/29/2008 8:30:50 AM

On 29 feb, 09:30, Sebastian Hanigk <han...@in.tum.de> wrote:
> "James Giles" <jamesgi...@worldnet.att.net> writes:
> > On the other hand, once you're familiar with the alternate
> > return feature, it's easier to read (and can often work faster
> > depending on the compiler). =A0If you have lots of code that
> > needs to be fault tolerant, the "obsolescent" alternate
> > return feature is the only kind of exception handling
> > feature Fortran has.
>
> I would advise against the alternate return facility from a software
> engineering point of view because it is in violation of the "single
> entry - single exit" directive. The simulation code I'm working with at
> the moment has routines with three, four, even five alternate returns
> which is a complete nightmare to read or extend (yes, the calling
> routines are sprinkled with labels and GOTOs, there is no consistency in
> label numbers, headaches galore).
>
> If you use the alternate return with only one alternative in a
> consistent manner, e.g. as a means to jump to a (consistently numbered)
> label for error handling, cleanup and the like, I don't think it's a bad
> idea as such - but a returned error code is in my opinion preferable.
>
> Sebastian

One thing that is attractive about alternate returns as
a means to capture exceptional circumstances (IMHO) is that
the user _has_ to decide what to do with them:

call some_routine( ..., error_code )
if ( error_code /=3D 0 ) then
    ... handle the error ...
endif

could easily become:

call some_routine( ..., dummy )


whereas:

call some_routine( ..., *999, error_code )

forces the user to at least clearly state that the
code should jump to some label.

He/she still has the option not to handle the error situation,
but anybody reading the code can see that there is
an alternate return involved.

Of course, having three or more alternate returns is
slightly exaggerating this visibility aspect.

Regards,

Arjen

0
Reply arjen.markus (2628) 2/29/2008 8:38:19 AM

On Feb 29, 8:38 am, Arjen Markus <arjen.mar...@wldelft.nl> wrote:
> On 29 feb, 09:30, Sebastian Hanigk <han...@in.tum.de> wrote:
>
>
>
> > "James Giles" <jamesgi...@worldnet.att.net> writes:
> > > On the other hand, once you're familiar with the alternate
> > > return feature, it's easier to read (and can often work faster
> > > depending on the compiler).  If you have lots of code that
> > > needs to be fault tolerant, the "obsolescent" alternate
> > > return feature is the only kind of exception handling
> > > feature Fortran has.
>
> > I would advise against the alternate return facility from a software
> > engineering point of view because it is in violation of the "single
> > entry - single exit" directive. The simulation code I'm working with at
> > the moment has routines with three, four, even five alternate returns
> > which is a complete nightmare to read or extend (yes, the calling
> > routines are sprinkled with labels and GOTOs, there is no consistency in
> > label numbers, headaches galore).
>
> > If you use the alternate return with only one alternative in a
> > consistent manner, e.g. as a means to jump to a (consistently numbered)
> > label for error handling, cleanup and the like, I don't think it's a bad
> > idea as such - but a returned error code is in my opinion preferable.
>
> > Sebastian
>
> One thing that is attractive about alternate returns as
> a means to capture exceptional circumstances (IMHO) is that
> the user _has_ to decide what to do with them:
>
> call some_routine( ..., error_code )
> if ( error_code /= 0 ) then
>     ... handle the error ...
> endif
>
> could easily become:
>
> call some_routine( ..., dummy )
>
> whereas:
>
> call some_routine( ..., *999, error_code )
>
> forces the user to at least clearly state that the
> code should jump to some label.
>
> He/she still has the option not to handle the error situation,
> but anybody reading the code can see that there is
> an alternate return involved.
>
> Of course, having three or more alternate returns is
> slightly exaggerating this visibility aspect.
>
> Regards,
>
> Arjen

I think you'll find that if you all a fortran subroutine in c then it
always returns a value and that value is the value of the alternate
return. It's probably compiler dependent but that was certainly my
experience 15 years ago when I was coding such things.

Simon
0
Reply simon9085 (164) 2/29/2008 1:01:38 PM

Arjen Markus <arjen.markus@wldelft.nl> writes:

> One thing that is attractive about alternate returns as
> a means to capture exceptional circumstances (IMHO) is that
> the user _has_ to decide what to do with them:
>
> call some_routine( ..., error_code )
> if ( error_code /= 0 ) then
>     ... handle the error ...
> endif
>
> could easily become:
>
> call some_routine( ..., dummy )

A major parallelisation library whose name shall not be given :-) forces
exactly this kind of code because the return value is in all but a few
pathological cases irrelevant.

Usually I'm employing a simple wrapping module which gives me a
F90/95/2003 interface with OPTIONAL dummy arguments for those libraries.

> whereas:
>
> call some_routine( ..., *999, error_code )
>
> forces the user to at least clearly state that the
> code should jump to some label.
>
> He/she still has the option not to handle the error situation,
> but anybody reading the code can see that there is
> an alternate return involved.

It's a good point you're bringing up, but I'm still not really
comfortable with alternate returns ...


Sebastian
0
Reply hanigk (201) 2/29/2008 2:35:43 PM

On 29 feb, 15:35, Sebastian Hanigk <han...@in.tum.de> wrote:
>
> > He/she still has the option not to handle the error situation,
> > but anybody reading the code can see that there is
> > an alternate return involved.
>
> It's a good point you're bringing up, but I'm still not really
> comfortable with alternate returns ...
>
> Sebastian

I have been programming quite a bit in Java of late,
and while exceptions are _the_ mechanism to handle
all manner of not-so-normal conditions there, I do not
feel they are the right thing either. (For instance:
a file that does not exist is hardly an exceptional
condition, is it? I would say that if reading a file
fails because it is corrupted, that is an exceptional
condition).
0
Reply arjen.markus (2628) 2/29/2008 2:45:03 PM

Arjen Markus <arjen.markus@wldelft.nl> writes:

> I have been programming quite a bit in Java of late,
> and while exceptions are _the_ mechanism to handle
> all manner of not-so-normal conditions there, I do not
> feel they are the right thing either. (For instance:
> a file that does not exist is hardly an exceptional
> condition, is it? I would say that if reading a file
> fails because it is corrupted, that is an exceptional
> condition).

How would you like to handle those conditions otherwise? In the end, an
exception (Java) is nothing else than a method's error code and some
syntactic sugar to hide a bit of complexity. Well, you could write your
Java classes in such a way that you do not employ exceptions but return
an error code instead, maybe it's a bit more efficient than the
try-catch mechanism (I heard that in C++ exception handling is very
costly). I would prefer to be able to enforce ignoring certain
exceptions like it's possible in Fortran with the IEEE FPEs; I surmise
the Java equivalent would be an empty catch block.


Sebastian
0
Reply hanigk (201) 2/29/2008 4:55:28 PM

Arjen Markus wrote:
....
> I have been programming quite a bit in Java of late,
> and while exceptions are _the_ mechanism to handle
> all manner of not-so-normal conditions there, I do not
> feel they are the right thing either. (For instance:
> a file that does not exist is hardly an exceptional
> condition, is it? [...]

Well aren't you making the assumption that the word "exception"
is synonymous with "error"?  I don't think it is.  And exception
might be needed for may things of which error handling is one
prominent example.  EOF would very often be another, even
in programs where it's not an error for the file to end.  Similarly
for non-existent files, EOR detection, even some varieties of
I/O error (that is, conditons the I/O library identifies as error
might not be from the point of view of the user's program).

-- 
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies."   --  C. A. R. Hoare 


0
Reply jamesgiles (2210) 2/29/2008 6:49:51 PM

Sebastian Hanigk wrote:
> "James Giles" <jamesgiles@worldnet.att.net> writes:
>
>> On the other hand, once you're familiar with the alternate
>> return feature, it's easier to read (and can often work faster
>> depending on the compiler).  If you have lots of code that
>> needs to be fault tolerant, the "obsolescent" alternate
>> return feature is the only kind of exception handling
>> feature Fortran has.
>
> I would advise against the alternate return facility from a software
> engineering point of view because it is in violation of the "single
> entry - single exit" directive. [...]

All exception handling does that.  If your program halts due
to error, that's a different "exit" than the usual one.  Not only
that: nearly all uses of "return codes" also take anomalous
control paths.  When people ask for "exception handling"
in a language, what they are *always* really asking for is
some form of anomalous control construct.

> If you use the alternate return with only one alternative in a
> consistent manner, e.g. as a means to jump to a (consistently
> numbered) label for error handling, cleanup and the like, I don't
> think it's a bad idea as such - but a returned error code is in my
> opinion preferable.

Which clutters the code with the redundant test on return and
probably just jumps to a label on each non-normal value of the
return code anyway.  All it does is falsely make the program
look like the main point of the procedure call was to set a
return code.  Consider the example given in annex B of the
Fortran document.  They want the following replacement:

      CALL SUBR_NAME (X, Y, Z, *100, *200, *300)

      may be replaced by

      CALL SUBR_NAME (X, Y, Z, RETURN_CODE)
      SELECT CASE (RETURN_CODE)
      CASE (1)
      ...
      CASE (2)
      ...
      CASE (3)
      ...
      CASE DEFAULT
      ...
      END SELECT

This is laughable - well, if it weren't so tragic.  No doubt people
will do this.  It replaces things that (correctly) look very much
like footnotes with an extra variable and (at least) 10 more lines
of code.  Assuming that the '...' aren't just GOTOs, the example
is probably considerably worse.  In may programs where such
fault tolerant techniques are required the source of middle-level
procedures tends to be a sequence of calls to lower-level procedures.
This is recommending that each call be turned into a dozen lines.
The actual purpose of the sequence will be lost in the clutter of the
return code handlers.

It's true that if Fortran actually had some exception handling
mechanism, the need for alternate returns would vanish.  At
present it's all we have.

-- 
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies."   --  C. A. R. Hoare 


0
Reply jamesgiles (2210) 2/29/2008 7:08:17 PM

"James Giles" <jamesgiles@worldnet.att.net> writes:

> Which clutters the code with the redundant test on return and
> probably just jumps to a label on each non-normal value of the
> return code anyway.  All it does is falsely make the program
> look like the main point of the procedure call was to set a
> return code.  Consider the example given in annex B of the
> Fortran document.  They want the following replacement:
>
>       CALL SUBR_NAME (X, Y, Z, *100, *200, *300)
>
>       may be replaced by
>
>       CALL SUBR_NAME (X, Y, Z, RETURN_CODE)
>       SELECT CASE (RETURN_CODE)
>       CASE (1)
>       ...
>       CASE (2)
>       ...
>       CASE (3)
>       ...
>       CASE DEFAULT
>       ...
>       END SELECT
>
> This is laughable - well, if it weren't so tragic.  No doubt people
> will do this.  It replaces things that (correctly) look very much
> like footnotes with an extra variable and (at least) 10 more lines
> of code.  Assuming that the '...' aren't just GOTOs, the example
> is probably considerably worse.

You may shake your head but I'm still convinced that the error code +
SELECT CASE variant is better than alternate returns. Why? Arjen's point
(forcing developers to provide exception handling) is certainly valid,
but often you simply do not care about error codes because critical ones
would abort your program anyway and uncritical ones are perhaps
unimportant enough.

Having forced alternate returns you will cluttering your code with a
plethora of labels or provide a dummy label like

CALL SUBR_NAME (X, Y, Z, *100, *100, *100)
100 CONTINUE

The SELECT CASE construct has the additional advantage (personal
opinion) that it makes the error handling explicit for the reader and it
is very local to the point where an error would have occurred.

I'm often arguing more from the point of view of a reader than developer
because most code will probably be read more often than written so it is
- apart from performance critical sections - of utmost importance to
support the reader.

> In may programs where such fault tolerant techniques are required the
> source of middle-level procedures tends to be a sequence of calls to
> lower-level procedures.  This is recommending that each call be turned
> into a dozen lines.  The actual purpose of the sequence will be lost
> in the clutter of the return code handlers.

For those middle-level routines I tend to write a small flowchart-like
explanation into the header commentary to guide the reader through the
calling sequence even if there are more other lines of code than calls
to subroutines.

> It's true that if Fortran actually had some exception handling
> mechanism, the need for alternate returns would vanish.  At
> present it's all we have.

I don't know if Fortran really needs such a facility. Its main strength
is after all scientific and numerical programming where from my - perhaps
rather small compared to other posters here - experience error
conditions are either fatal or negligible. One of the simulation codes
here does a steady-state computation before beginning the transient
part, it makes really no sense to run the transient part if the
steady-state calculation has not converged, so I do not throw some
"HasNotConverged" exception, logging the error condition and aborting
is much more sensible.


Sebastian
0
Reply hanigk (201) 3/1/2008 8:57:55 AM

On 29 feb, 19:49, "James Giles" <jamesgi...@worldnet.att.net> wrote:

>
> Well aren't you making the assumption that the word "exception"
> is synonymous with "error"?  I don't think it is.  And exception
> might be needed for may things of which error handling is one
> prominent example.  EOF would very often be another, even
> in programs where it's not an error for the file to end.  Similarly
> for non-existent files, EOR detection, even some varieties of
> I/O error (that is, conditons the I/O library identifies as error
> might not be from the point of view of the user's program).
>

Perhaps it is a matter of semantics:
To me (at least in day-to-the-day use of the natural languages
I am familiar with) an exception is, well, a situation that does
not follow the rules. But for a file there are two rules
(from the house-kitchen-garden point of view, to use a neerlandicism):
- It exists and you are allowed to read its contents
- It does not exist or you are not allowed to read its contents

It feels strange to consider the second rule an exception (to
apparently
the first). But perhaps I am also annoyed by all the policies
that surround exceptions in Java, of a "thou shalt not ..." kind of
nature.

Anyway, this is digressing far from the original topic ;).

I would say, that if there is a fatal circumstance in a library,
the library should be able to communicate this to the caller and
it is the caller's responsibility to deal with it. Simply stop the
program is too severe - it reminds me of the dreaded "blue screen
of death".

But then, I immediately admit that it is very difficult to give
guidelines for what a library should consider a fatal circumstance.
And how to communicate it to the user.

A small, everyday, example:

If you open a file (in Fortran), you can check that it succeeded
or not. If not, you must decide if there is a way to continue the
processing.

For, say, a file with run-time options you can probably supply default
values and go on with the actual processing. If it is a data file
containing the data your program needs to process, the primary data
so to say, there is probably not much you can do.

In that case, how do you, as a library designer, communicate this
problem to the calling program and ultimately to the human user?
You could do it in a very detailed way:
    The OPEN statement on file such and such failed with this error
    code, please check the manual of your compiler to see what that
    code means. Or even friendlier: try and detect reasons for the
    failure and communicate them via return codes/alternate returns:
    1 - No file name given
    2 - File does not exist at all
    3 - Disk drive not available
    4 - File permissions are wrong
    5 - File has an unexpected structure (after reading the magic
number say)
    6 - Some other error (along with the error code from the OPEN
statement)

You could also simply say:
    Opening file such and such failed

Or something in between.


Regards,

Arjen

0
Reply arjen.markus (2628) 3/1/2008 9:50:55 AM

Sebastian Hanigk wrote:
> "James Giles" <jamesgiles@worldnet.att.net> writes:
> 

[snip (James Giles' dislike of using SELECT CASE over alt RETURNs)]

> 
> You may shake your head but I'm still convinced that the error code +
> SELECT CASE variant is better than alternate returns. Why? Arjen's point
> (forcing developers to provide exception handling) is certainly valid,
> but often you simply do not care about error codes because critical ones
> would abort your program anyway and uncritical ones are perhaps
> unimportant enough.

I've found forcing developers to do anything as pretty much impossible unless 
noncompliance involves so $$ penalty (via some mechanism)

(my very cynical personal opinion only, of course. Not speaking officially for my 
employers or affiliates. :o)

> Having forced alternate returns you will cluttering your code with a
> plethora of labels or provide a dummy label like
> 
> CALL SUBR_NAME (X, Y, Z, *100, *100, *100)
> 100 CONTINUE
> 
> The SELECT CASE construct has the additional advantage (personal
> opinion) that it makes the error handling explicit for the reader and it
> is very local to the point where an error would have occurred.

On a purely personal basis, I agree with Sebastian. I much prefer the error handling to be 
local, i.e. close to where it occurred. Having said that, I still do a lot of stuff like 
below, i.e. specify an error (or warning message) close to where the error occurred, and 
then call an internal to handle the common cleanup stuff.

   function myfunc(....args.....) result(error_status)
     use message_handler, only: SUCCESS, FAILURE, Display_Message
     ! arguments decls
     ....
     ! function result
     integer :: error_status
     ! local parameters
     character(*), parameter :: ROUTINE_NAME = 'myfunc'
     ! local variables
     character(256) :: message
     integer :: local_error_status
     ! init result
     error_status = SUCCESS

     ....code bits....
     local_error_status = some_other_func(.....)
     if ( local_error_status /= SUCCESS ) then
       messsage = 'error occurred in some_other_func'
       call myfunc_cleanup()
       return
     end if

     ....more code bits....
     if ( some_number < what_it_should_be ) then
       messsage = 'invalid some_number value'
       call myfunc_cleanup()
       return
     end if
     ......

   contains

     subroutine myfunc_cleanup
       error_status = FAILURE
       call Display_Message( ROUTINE_NAME, trim(message), error_status )
       ... do other cleanup as necessary....
       ... e.g. deallocate structures with pointer members, nullify,
           close files, etc....
     end subroutine myfunc_cleanup
   end function myfunc

with suitable modifications for a WARNING status. I.e. calcs can continue and still may be 
correct, but user should suspect and inspect results.

> I'm often arguing more from the point of view of a reader than developer
> because most code will probably be read more often than written so it is
> - apart from performance critical sections - of utmost importance to
> support the reader.
> 
>> In may programs where such fault tolerant techniques are required the
>> source of middle-level procedures tends to be a sequence of calls to
>> lower-level procedures.  This is recommending that each call be turned
>> into a dozen lines.  The actual purpose of the sequence will be lost
>> in the clutter of the return code handlers.
> 
> For those middle-level routines I tend to write a small flowchart-like
> explanation into the header commentary to guide the reader through the
> calling sequence even if there are more other lines of code than calls
> to subroutines.
> 
>> It's true that if Fortran actually had some exception handling
>> mechanism, the need for alternate returns would vanish.  At
>> present it's all we have.
> 
> I don't know if Fortran really needs such a facility. Its main strength
> is after all scientific and numerical programming where from my - perhaps
> rather small compared to other posters here - experience error
> conditions are either fatal or negligible. One of the simulation codes
> here does a steady-state computation before beginning the transient
> part, it makes really no sense to run the transient part if the
> steady-state calculation has not converged, so I do not throw some
> "HasNotConverged" exception, logging the error condition and aborting
> is much more sensible.

In my IDL functions, I do the following

FUNCTION myfunc, ...args...

   ; Set up error handling
   @error_codes
   CATCH, Error_Status
   IF ( Error_Status NE 0 ) THEN BEGIN
     CATCH, /CANCEL
     HELP, /LAST_MESSAGE
     MESSAGE, !ERROR_STATE.MSG, /CONTINUE
     FREE_LUN, FileID
     ...other stuff for cleanup if necessary....
     RETURN, FAILURE
   ENDIF

   ; Open the file
   FileID = Open_Binary_File( Filename )
   IF ( FileID < 0 ) THEN $
     MESSAGE, 'Error opening file '+Filename, $
              /NONAME, /NOPRINT

   ; Read stuff from file
   result = read_stuff( FileID, ...args... )
   IF ( result NE SUCCESS ) THEN $
     MESSAGE, 'Error reading data from '+Filename, $
              /NONAME, /NOPRINT

   ....etc...
END


I would like something like this capability in Fortran if only to be able to put the error 
handling up front.

Anyway....

cheers.

paulv
0
Reply paul.vandelst (1947) 3/3/2008 2:45:16 PM

Paul van Delst wrote:
> Sebastian Hanigk wrote:
>> "James Giles" <jamesgiles@worldnet.att.net> writes:
>>
>
> [snip (James Giles' dislike of using SELECT CASE over alt RETURNs)]
>
>>
>> You may shake your head but I'm still convinced that the error code +
>> SELECT CASE variant is better than alternate returns. Why? Arjen's
>> point (forcing developers to provide exception handling) is
>> certainly valid, but often you simply do not care about error codes
>> because critical ones would abort your program anyway and uncritical
>> ones are perhaps unimportant enough.
>
> I've found forcing developers to do anything as pretty much
> impossible unless noncompliance involves so $$ penalty (via some
> mechanism)

Increased maintenance cost dealing with return codes is rather
significant.  The main reason that most other languages now have
exception handling mechanisms is in recognition of that uncomfortable
fact.  It's not like using return codes was unavailable in those
languages - they clearly could already do that before they added
exception handling as a feature.

One of the reasons I don't like the exception handling features of
most other languages is that they don't even mention the possibility
of error locally.  That is, if A calls B which then calls C, and an
exception occurs in C there will be no indication in the source
code of B that C's return will be to some handler in A.  The
author of B might indeed be unaware that C might raise exceptions
that it doesn't handle itself.  This causes hard to find problems
(since A might have a handler for the exception because of
a known possibility of the condition right there in A: the
handler has no notion of how to correctly handle problems
coming from C).  I've seen these myself in several Ada codes.
Or, B might have some things it needs to deallocate or files
to close and be deprived of the opportunity because C didn't
return.  I've seen that problem many times too.

As I've said before, most people's objections to alternate returns
would disappear if the thing after the * on the call was the name
of an exception handler and not a statement label.  It would
otherwise be the same feature, but somehow most people
seem to find it more acceptable.  It still provides a local
indication of the possibility of error as well as a way for to
locally perform some necessary operations (like the last
sentence in that previous paragraph), before returning to
things higher up in the call stack.  And it still doesn't intermix
the code for proper operation of the program with code to
handle rare anomalies, nor does it require statements that
make redundant tests (*ALL* tests of return codes are redundant,
the procedure that returned them has already decided whether
the exception has arisen or not).

In any case, I don't care it other people *don't* use alternate
return.  Just don't deprive me of being allowed to use it.  At
least not until some genuinely better form of exception handling
is available.

Note: most of the objections still seem to be coming from people
who regard exception handling as something that allows them
to "clean-up" before terminating.  That should actually be a separate
feature (i.e. how should the program respond to a terminate signal?).
Exceptions should be used only for two purposes: 1) to correct
the problem so the program can continue running or 2) to refer the
decision about whether the problem is fatal to some other part
of the program.

-- 
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies."   --  C. A. R. Hoare 


0
Reply jamesgiles (2210) 3/3/2008 6:14:32 PM

On 2008-03-03 14:14:32 -0400, "James Giles" <jamesgiles@worldnet.att.net> said:

> Paul van Delst wrote:
>> Sebastian Hanigk wrote:
>>> "James Giles" <jamesgiles@worldnet.att.net> writes:
>>> 
>> 
>> [snip (James Giles' dislike of using SELECT CASE over alt RETURNs)]
>> 
>>> 
>>> You may shake your head but I'm still convinced that the error code +
>>> SELECT CASE variant is better than alternate returns. Why? Arjen's
>>> point (forcing developers to provide exception handling) is
>>> certainly valid, but often you simply do not care about error codes
>>> because critical ones would abort your program anyway and uncritical
>>> ones are perhaps unimportant enough.
>> 
>> I've found forcing developers to do anything as pretty much
>> impossible unless noncompliance involves so $$ penalty (via some
>> mechanism)
> 
> Increased maintenance cost dealing with return codes is rather
> significant.  The main reason that most other languages now have
> exception handling mechanisms is in recognition of that uncomfortable
> fact.  It's not like using return codes was unavailable in those
> languages - they clearly could already do that before they added
> exception handling as a feature.
> 
> One of the reasons I don't like the exception handling features of
> most other languages is that they don't even mention the possibility
> of error locally.  That is, if A calls B which then calls C, and an
> exception occurs in C there will be no indication in the source
> code of B that C's return will be to some handler in A.  The
> author of B might indeed be unaware that C might raise exceptions
> that it doesn't handle itself.  This causes hard to find problems
> (since A might have a handler for the exception because of
> a known possibility of the condition right there in A: the
> handler has no notion of how to correctly handle problems
> coming from C).  I've seen these myself in several Ada codes.
> Or, B might have some things it needs to deallocate or files
> to close and be deprived of the opportunity because C didn't
> return.  I've seen that problem many times too.
> 
> As I've said before, most people's objections to alternate returns
> would disappear if the thing after the * on the call was the name
> of an exception handler and not a statement label.  It would
> otherwise be the same feature, but somehow most people
> seem to find it more acceptable.  It still provides a local
> indication of the possibility of error as well as a way for to
> locally perform some necessary operations (like the last
> sentence in that previous paragraph), before returning to
> things higher up in the call stack.  And it still doesn't intermix
> the code for proper operation of the program with code to
> handle rare anomalies, nor does it require statements that
> make redundant tests (*ALL* tests of return codes are redundant,
> the procedure that returned them has already decided whether
> the exception has arisen or not).
> 
> In any case, I don't care it other people *don't* use alternate
> return.  Just don't deprive me of being allowed to use it.  At
> least not until some genuinely better form of exception handling
> is available.
> 
> Note: most of the objections still seem to be coming from people
> who regard exception handling as something that allows them
> to "clean-up" before terminating.  That should actually be a separate
> feature (i.e. how should the program respond to a terminate signal?).
> Exceptions should be used only for two purposes: 1) to correct
> the problem so the program can continue running or 2) to refer the
> decision about whether the problem is fatal to some other part
> of the program.

When set up with a SELECT CASE statement as James showed, one can
use parameters to assign error codes and further use meaningful names
for the parameters. It makes things readable by the human as well
as the machine. (I can only agree with James that SELECT CASE is
an inferior second choice that is only made more palatable when made
readable.)

The same argument for readability suggests that statement labels
are long overdue for alphanumeric names. A small rewriting of the
rules for construct names would do the job. Unfortunately small is
not minor so would take a bit of work to allow the construct name
of a DO to also be a GOTO target. An optional colon that would be
frequently required in fixed form source would address the fixed
form issues. The bookkeeping of statement numbers for error exits
is a commonly cited software engineering bother in Fortran.  (Is
9000 end-of-file or is it end-of-record?)

Alphanumeric labels would also have the merit of removing an easy
target of ridicule in FORTRAN(sic). The comments would still be
made by those trained in F66 but a technically correct rebuttal
would be possible.



0
Reply g.sande (1183) 3/3/2008 7:35:24 PM

James Giles wrote:

> One of the reasons I don't like the exception handling features of
> most other languages is that they don't even mention the possibility
> of error locally.  That is, if A calls B which then calls C, and an
> exception occurs in C there will be no indication in the source
> code of B that C's return will be to some handler in A.  

Look at Java.  Every exception must either be caught or the method
declared to throw that exception.  The compiler will detect if it
isn't one or the other and the compilation will fail.
(Either the specific exception of a superclass of it.)

For quick debugging tests, I sometimes do

public static void main(String args[]) throws Exception;

such that I don't need to catch any exceptions in main,
all will be fatal and indicated with a message.
(Exception is the superclass of all exceptions.)

In contrast, C uses the return value of many functions to
indicate exceptions, encouraging the programmer to ignore them.
Two important routines where the return value is commonly
ignored are printf() and fclose().   With buffering, the only
notice that a file write failed might be in the call to fclose().

-- glen

0
Reply gah (12303) 3/3/2008 10:45:25 PM

glen herrmannsfeldt wrote:
> James Giles wrote:
>
>> One of the reasons I don't like the exception handling features of
>> most other languages is that they don't even mention the possibility
>> of error locally.  That is, if A calls B which then calls C, and an
>> exception occurs in C there will be no indication in the source
>> code of B that C's return will be to some handler in A.
>
> Look at Java.  [...]

Indeed.  Readers of this thread might benefit from reading:
  http://java.sun.com/docs/books/tutorial/essential/exceptions/advantages.html

-- 
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies."   --  C. A. R. Hoare 


0
Reply jamesgiles (2210) 3/4/2008 12:53:29 AM

> One of the reasons I don't like the exception handling features of
> most other languages is that they don't even mention the possibility
> of error locally.  That is, if A calls B which then calls C, and an
> exception occurs in C there will be no indication in the source
> code of B that C's return will be to some handler in A.  The
> author of B might indeed be unaware that C might raise exceptions
> that it doesn't handle itself.  This causes hard to find problems
> (since A might have a handler for the exception because of
> a known possibility of the condition right there in A: the
> handler has no notion of how to correctly handle problems
> coming from C).  I've seen these myself in several Ada codes.
> Or, B might have some things it needs to deallocate or files
> to close and be deprived of the opportunity because C didn't
> return.  I've seen that problem many times too.

All these are indicative of an incorrectly designed exception handling 
system. The only exception handling system that I know intimately - the 
one designed for VMS - provides exactly for those scenarios in a way 
that is reasonably easy to use.

> And it still doesn't intermix
> the code for proper operation of the program with code to
> handle rare anomalies, nor does it require statements that
> make redundant tests (*ALL* tests of return codes are redundant,
> the procedure that returned them has already decided whether
> the exception has arisen or not).

In this connection, making an exception handling facility available at 
all has significant performance implications on modern processors, which 
return codes do not have. Finding the proper balance is not easy. Do you 
want to pay for this, for instance, on every math library call, or would 
you rather handle it using NANs when and where required?

> Note: most of the objections still seem to be coming from people
> who regard exception handling as something that allows them
> to "clean-up" before terminating.  That should actually be a separate
> feature (i.e. how should the program respond to a terminate signal?).
> Exceptions should be used only for two purposes: 1) to correct
> the problem so the program can continue running or 2) to refer the
> decision about whether the problem is fatal to some other part
> of the program.

Agreed.

	Jan
0
Reply Jan.Vorbrueggen (131) 3/4/2008 11:44:48 AM

On Mar 4, 4:44=A0am, Jan Vorbr=FCggen <Jan.Vorbrueg...@not-thomson.net>
wrote:
=2E..
> > And it still doesn't intermix
> > the code for proper operation of the program with code to
> > handle rare anomalies, nor does it require statements that
> > make redundant tests (*ALL* tests of return codes are redundant,
> > the procedure that returned them has already decided whether
> > the exception has arisen or not).
>
> In this connection, making an exception handling facility available at
> all has significant performance implications on modern processors, which
> return codes do not have. Finding the proper balance is not easy. Do you
> want to pay for this, for instance, on every math library call, or would
> you rather handle it using NANs when and where required?

I wasn't speaking here particularly about performance, but about code
clutter.  Excessive redundant tests are not the kind of things that
enhance legibility.  If return codes are your only means of dealing
with anomalous situations, fault tolerant programs often get quite
illegible.

--
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies."   --  C. A. R. Hoare
0
Reply jamesgiles1 (157) 3/5/2008 2:02:26 AM

On 2008-03-03, James Giles <jamesgiles@worldnet.att.net> wrote:
> One of the reasons I don't like the exception handling features of
> most other languages is that they don't even mention the possibility
> of error locally.  That is, if A calls B which then calls C, and an
> exception occurs in C there will be no indication in the source
> code of B that C's return will be to some handler in A.  The
> author of B might indeed be unaware that C might raise exceptions
> that it doesn't handle itself.  This causes hard to find problems
> (since A might have a handler for the exception because of
> a known possibility of the condition right there in A: the
> handler has no notion of how to correctly handle problems
> coming from C).  I've seen these myself in several Ada codes.
> Or, B might have some things it needs to deallocate or files
> to close and be deprived of the opportunity because C didn't
> return.  I've seen that problem many times too.

Yes. A nice solution is the with-open-file style construct in Common
LISP or it's IDisposable/using equivalent in C#. It's basically a way
of specifying that certain functions are called when one exits a
block, whether by normal control flow or after an exception. Since
both C# and LISP have GC, this is typically used for cleanup up
non-memory resources such as file handles.

For non-GC languages, perhaps something like RAII typically used in
C++ would be more useful. OTOH C++ provides an example of the dangers
of exception style control flow in non-GC languages, as two of the
more popular non-beginner C++ books are big tomes dedicated to
explaining non-intuitive ways that you can shoot yourself in the foot
wrt exception safety unless you're really really careful (the books
I'm thinking of are Exceptional C++ and More Exceptional C++ by Herb
Sutter).

> Exceptions should be used only for two purposes: 1) to correct
> the problem so the program can continue running or 2) to refer the
> decision about whether the problem is fatal to some other part
> of the program.

I think that might be an unnecessarily strict interpretation.  A few
years ago I was working on a web application implemented in Java. The
second major iteration of the design was, if I may say so myself,
quite nice. With these kinds of applications a lot of stuff is I/O, be
it database, file, or network I/O, and all of these can throw
exceptions in Java. So done the "classical" way it lead to an
explosion in code size due to all the try/catch. The basic idea
wrt. exceptions that we adopted was that we used unchecked exceptions
basically everywhere. Contrary to what Glen said in another response
to your message, Java supports unchecked exceptions just fine (we used
a library that wrapped most of the standard checked exceptions in
unchecked ones). In the few cases where an exception actually was
correctable, it was of course caught and fixed as soon as possible,
but all the other exceptions flowed up to a "catch-all" exception
handler that logged the stack trace, showed a friendly error message
to the user, and IIRC reset some session related data so that the user
could continue from a consistent state. Since this was multiuser
server software, shutting down the entire program due to an exception
was not acceptable. So this is close, but not quite, your #1 purpose
above.


-- 
Janne Blomqvist
0
Reply foo33 (1360) 3/6/2008 8:24:48 PM

Janne Blomqvist wrote:
> On 2008-03-03, James Giles <jamesgiles@worldnet.att.net> wrote:
(snip)

>>Exceptions should be used only for two purposes: 1) to correct
>>the problem so the program can continue running or 2) to refer the
>>decision about whether the problem is fatal to some other part
>>of the program.

> I think that might be an unnecessarily strict interpretation.  A few
> years ago I was working on a web application implemented in Java. The
> second major iteration of the design was, if I may say so myself,
> quite nice. With these kinds of applications a lot of stuff is I/O, be
> it database, file, or network I/O, and all of these can throw
> exceptions in Java. So done the "classical" way it lead to an
> explosion in code size due to all the try/catch. The basic idea
> wrt. exceptions that we adopted was that we used unchecked exceptions
> basically everywhere. Contrary to what Glen said in another response
> to your message, Java supports unchecked exceptions just fine (we used
> a library that wrapped most of the standard checked exceptions in
> unchecked ones). 

 From "The Java Programming Language, Third Edition"

1.13  "Unchecked exceptions represent conditions that, generally
       speaking, reflect errors in your program logic and cannot be
       reasonably recovered from at run time.  For example, the
       IndexOutOfBoundsException thrown when you access outside the
       bounds or an array, tells you that your program calculated
       an index incorrectly, or failed to verify a value used as in
       index.  These are errors that should be corrected in the program
       code.  Given that you can make errors writing any statement, it
       would be totally impractical to have to declare or catch all the
       exceptions that could arise from those errors."

Note that in Java bounds checking is not optional.

8.1   "Exceptions are primarily checked exceptions, meaning that the
       compiler checks that your methods throws only exceptions that
       they have declared themselves to throw.  The standard runtime
       exceptions extend one of the classes RuntimeExeption and Error,
       making them unchecked exceptions.  All exceptions that you create
       should extend Exception, making them checked exceptions."

It would be extra work, and not very useful, to require all methods to
declare throws IndexOutOfBoundsException if they used an array.  On the
other hand, it isn't all that much work to declare any exceptions that
you create with a throws clause.   If you call a method that is declared
to throw an exception, you either have to catch it or declare it in
a throws clause.  Note above: "All exceptions that you create should
extend Exception, making them checked exceptions."   Or, you can just 
add throws Exception onto all methods and ignore them.

-- glen

0
Reply gah (12303) 3/6/2008 9:30:02 PM

jamesgiles@att.net wrote:
(snip)

> I wasn't speaking here particularly about performance, but about code
> clutter.  Excessive redundant tests are not the kind of things that
> enhance legibility.  If return codes are your only means of dealing
> with anomalous situations, fault tolerant programs often get quite
> illegible.

or people give up before testing everything.
(Especially considering the difficulty of testing the tests.)

Though if you have a properly coded return code you can pass
it up to the next level with one test and one GOTO or RETURN.

-- glen

0
Reply gah (12303) 3/6/2008 10:20:21 PM

25 Replies
36 Views

(page loaded in 2.176 seconds)


Reply: