comp.lang.ada
 help / color / mirror / Atom feed
From: "Robert I. Eachus" <rieachus@attbi.com>
Subject: Re: Ada style of passing 'in' parameters considered dangerous?
Date: Sun, 09 Feb 2003 07:13:26 GMT
Date: 2003-02-09T07:13:26+00:00	[thread overview]
Message-ID: <3E45FFCB.90109@attbi.com> (raw)
In-Reply-To: wcc3cmyw6t5.fsf@shell01.TheWorld.com

Robert A Duff wrote:

> The problem with this Ada rule is that it violates abstraction.
> You don't know whose responsibility it is to worry about aliases
> -- the caller or callee.

The callee.  The abstraction rules in Ada basically mean that the callee 
has to support all possible callers, including those that don't exist 
yet.  In addition, there is the assumption that anything that the user 
of a package needs can be found in the package specification.  (Of 
course, many people including myself are quite willing to use comments 
in the specification to document assumptions made by the body, 
exceptions that may be raised, etc.)

> How about this example:
> 
> We have a record representing fractions of whole numbers:
> 
>     type Fraction is
>         record
>             Numerator: Integer;
>             Denominator: Positive;
>         end record;
> 
>     procedure Reciprocal(Result: out Fraction; X: Fraction);
>     -- Sets Result to the reciprocal of X.
> 
>     procedure Reciprocal(Result: out Fraction; X: Fraction) is
>     begin
>         if X.Numerator > 0 then
>             Result.Numerator := X.Denominator;
>             Result.Denominator := X.Numerator;
>         ... etc
> 
> It seems reasonable (without seeing the body of Reciprocal) to do:
> 
>     Reciprocal(Foo, Foo);
> 
> If Fractions are passed by copy (which is probably most efficient, since
> they fit in just two registers), then it works fine.  If they're passed
> by reference, we get the wrong answer.

...and if you write the body as:

  procedure Reciprocal(Result: out Fraction; X: Fraction) is
      begin
          if X.Numerator > 0 then
              Result := (X.Denominator, X.Numerator);
          ... etc

There is no problem.  (The aggregate must be completely evaluated before 
it can be assigned.) Of course it makes more sense to implement this as 
a function:

  function Reciprocal(X: Fraction) return Fraction is
      begin
          if X.Numerator > 0 then
              return (X.Denominator, X.Numerator);
          ... etc

If the subprogram is inlined, then calls of the form Reciprocal(Foo, 
Foo); or Foo := Reciprocal(Foo); may require more instructions than 
Reciprocal(Foo, Bar) or Bar := Reciprocal(Foo);  But this is not a 
problem, it is exactly what you want--the most efficient code in either 
case.

So in general, the problem of aliasing exists in all high level 
languages, and different language take different approaches to defining 
what happens in the painful, sometimes not even possible to recognize 
even at execution time, cases.  However, in well written Ada there are 
very few cases where the issue is likely to come up.  This is because 
Ada provides lots of ways for a subprogram or body to be written in a 
way that makes its correctness independent of aliasing and parameter 
passing conventions.

But the most important thing to remember is that in Ada the place to 
solve the (potential) problem is in the body of the callee, not in the 
caller or the specification of the callee.  For example, if you have a 
record parameter and must force copy semantics, simply write:

procedure Reciprocal(Result: out Fraction; X: Fraction) is
   Temp := X;
begin...

If the compiler passes X by copy, any decent optimizer will eliminate 
the "second" copy.  If you later change the code as (way) above and 
don't need to force copy semantics, you only have to change the 
body--which you are doing anyway--and not the specification (forcing 
recompiles) or all of the callers.




  parent reply	other threads:[~2003-02-09  7:13 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-02-08 22:24 Ada style of passing 'in' parameters considered dangerous? Antti Sykari
2003-02-09  0:41 ` James S. Rogers
2003-02-09  2:11   ` Robert A Duff
2003-02-09  2:25   ` Jeffrey Carter
2003-02-11  8:39   ` Gautier
2003-02-09  2:01 ` Robert A Duff
2003-02-09  2:33   ` Vinzent Hoefler
2003-02-09  6:07   ` Richard Riehle
2003-02-09  7:13   ` Robert I. Eachus [this message]
2003-02-10  4:40     ` Martin Dowie
2003-02-09  2:08 ` Jeffrey Carter
2003-02-10  0:13 ` Leif Holmgren
2003-02-10  9:49 ` Rod Chapman
2003-02-11  9:14 ` Gautier
2003-02-11 13:49   ` Antti Sykari
2003-02-11 17:18   ` Gautier
2003-02-11 17:29     ` Vinzent Hoefler
2003-02-12  1:09   ` Richard Riehle
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox