Christoph & Ursula Grein wrote:
>
> > > The obvious solution is to always assign a value to the parameter, but this
> >  may not always be possible.  For example, we have generic containers with
> >  methods that can return a component and a validity flag.  If a component can
> >  not be returned, the container assigns nothing to the component parameter,
> >  and sets the validity parameter appropriately.  Unfortunately, the
> >  containers have no formal nil object in there specification, and therefor
> >  cannot return a safe value.  Again, to change a generic spec. can have
> >  significant ripple effect on other units.
>
> If adding such a nil object is impossible, try the suppress pragmas. This should
> solve the problem. (In any case, the clean and preferable solution would be the
> nil object.)

The clean and preferable solution depends on the nature of the
operation. If an invalid object is an exceptional situation, as in the
case of misuse of the container by trying to remove something from it
when it is empty, then raising an exception is the clean and preferable
solution.

In other cases, raising an exception is not the best solution. Consider,
for example, searching for a pattern in a string, and returning the
index in the string at which the pattern starts. One could build a
search program that outputs the lines of text file that match a pattern
with such a function (such as grep). Most of the lines in a file will
not match the pattern. How should such a function signal "no match"?

Booch's regular-expression component raises an exception to signal "no
match". Since in a common application of the component (grep) "no match"
is the most common result, it is not an exceptional situation and an
exception is the wrong way to indicate it.

The Ada.Strings packages return an invalid index (zero) to indicate "no
match". This is better than an exception, but uses one thing to
represent two different concepts, and so violates a basic
software-engineering principle.

Avoiding this violation of basic principles requires defining a result
type for the function:

type Index_Result (Found : Boolean := False) is record
   case Found is
   when False =>
      null;
   when True =>
      Start : Positive;
   end case;
end record;

This same manner of thinking results in a similar type being the out
parameter from the container operation. Such a parameter would always be
set correctly by the operation whether or not the operation can return a
valid value, and regardless of the parameter passing mechanism used by
the compiler for the type. Thus we see that with proper attention to
software engineering this problem does not arise.

--
Jeff Carter
"You cheesy lot of second-hand electric donkey-bottom biters."
Monty Python & the Holy Grail