May out-parameters be read?

Christoph Karl Walter Grein

There is a darned Ada83 rule forbidding reading formal out-parameters. You often find some contorted code to cope with this restriction - even in cases where it is absolutely unnecessary.

Suppose you have a bunch of documents (a discriminated record) you want to store. So you declare the following package:

package Archive is

  type Key_Template is (Desk, Safe, ...);

  type Document (Key: Key_Template := Desk) is record
    case Key is
      when Desk => Confidential: ...;
      when Safe => Secret      : ...;
      when ...
    end case;
  end record;

  procedure Store    (Letter: in Document);
  procedure Retrieve (<Parameters>);

end Archive;

package body Archive is

  Storage: array (Key_Template) of Document;

  procedure Store (Letter: in Document) is
  begin
    Storage (Letter.Key) := Letter;
  end Store;

  procedure Retrieve (<Parameters>) is
  begin
    ?
  end Retrieve;

end Archive;

Now our poor programmer is brooding about how to define the retrieve operation.

which has the wrong mode in out (it's a pure out parameter), or

which is unnecessarily tedious because of the first parameter use_Key. Now if you ask why all these contortions instead of the simple and correct and symmetric

you will undoubtedly and invariably get the answer: "But you can't read out-parameters."

Of course you can, at least some parts - of arrays, you may read the limits, of records, you may read the discriminants and the limits and discriminants ot their components, ARM_83 6.2 (5).

Why is this so? Well, how else should the following ever work?

Everyone knows Text_IO. Here Text is the actual parameter for the formal out-parameter Item, and in the body of Get_Line, something like the following happens:

The attributes Item'First [21], Item'Last [30], Item'Range may be used to read the limits [the values for our example are given in brackets].

Thus the solution for our key problem is

and we empty the safe like so:

When however nothing has ever before been stored in the safe, we get Constraint_Error. Have we forgotten something?

Solution