Version 1.2 of ai05s/ai05-0143-1.txt
!standard 6.01 (18) 09-04-30 AI05-0143-1/02
!standard 6.06 (03)
!class Amendment 09-02-15
!status work item 09-02-15
!status received 09-02-15
!subject In Out parameters for functions
Parameters of all modes are allowed in functions.
The restriction on parameter modes for functions is an embarassing wart on
the language. Ada functions can have arbitrary side-effects, but are not
allowed to announce that in their specifications.
When constructing reusable object-oriented abstractions, it is important to
allow future extensions to have the maximum flexibility. This means that
parameters of object-oriented types should generally be declared as in out,
so that future extensions can modify the parameter's contents if necessary.
However, this prevents using functions for most operations. If there is any
conceptual chance of an extension needing to modify its argument, then
a function cannot be used. Even for operations that are conceptually pure,
caching of results may require modification of extensions.
If an unconstrained type (such as String) needs to be returned, there is no
real alternative to using a function.
When this problem occurs, only three solutions are possible:
-- Abandon functions;
-- Use the functions, leaving the onus of solving the problem on
-- Use an access parameter.
For the second solution, the author of an extension would have to allocate (probably
from the heap) a separate, writable object, and include an access to
it in the extension. This means the author now has to handle memory
management (with all of its possibilities for errors, like storage
leaks and double freeing) which they previously did not have to do.
Access parameters are a very flawed solution as well. Access parameters require
altering the calling syntax of calls to the function (to include an approriate
'Access, or to remove a dereference). They also require altering the declaration
of the object to be passed (to include "aliased"). Finally, access parameters
are more expensive at run-time than regular parameter passing, as they are
required to include a run-tine indication of their accessibility level. The
run-time check can even be dangerous, as the check may fail only with
arguments declared in nested scopes, and that may not happen in unit testing.
for all of these reasons, the restriction on parameter modes for functions
has been removed.
The last sentence of 6.1(18) is deleted.
Add "of mode in" to 6.6(3):
The subprogram_specification of a unary or binary operator shall have one or
two parameters of mode in, respectively. A generic function instantiation whose
designator is an operator_symbol is only allowed if the specification of the
generic function has the corresponding number of parameters of mode in and no
The primary technical argument against allowing "in out" and "out" parameters
in function calls is that there is not much visibility of the side-effects,
and thus they make it more likely that order-dependent expressions are created.
However, the existing features of the language (especially the combination
of access parameters and prefix notation) make it possible to write the majority
of examples of incorrect order dependence in Ada as it exists today. Specifically,
access parameters are very similar semantically to "in out" by-reference
parameters, and they are allowed on functions already. They just provide a
less convenient syntax and are less efficient (because of the possibility of
dynamic accessibility checks) than "in out" parameters would be.
As one commenter put described our current situation with incorrect order
dependence, we're already in a deep pit, and if we're not at the bottom
already, we're only a few centimeters above it. Thus, the problem of incorrect
order dependence is one that should be addressed irrespective of "in out"
parameters for functions, and surely should not be used as an excuse to
"throw out the baby with the bathwater". (The problem of incorrect order
dependence is discussed in AI05-0144-1, including plenty of examples.)
Operator symbols are conceptually functions with one or two in parameters.
We do not want infix expressions to have side effects on their arguments.
Thus, we add wording to restrict operator symbols to parameters of mode in.
We considered using the presense of "in out" parameters on a function to
signal that the function needs read-write access to the protected object.
This is a capability that is sorely missing from Ada, as the current rules
force programmers to use procedures when they really want functions. As
noted in the description of the initial problem, it is not always possible
to convert a function into a similar procedure call, and even when it is
possible, the result is harder to use than necessary.
However, the presense of "in out" parameters doesn't really tell us whether
or not we need write access to the protected object; it is perfectly reasonable
to modify a parameter but not the protected object. This imperfect description
is no better than the current situation in the eyes of some reviewers (an
opinion not shared by the author).
In addition, adding read-write function access to protected objects could
have a significant impact on implementations. The problem is not judged
important enough (and the solution not good enough) in order to incur this
In the Claw Builder, we have a function that can return an
access to the actual Claw object for simulation. This function is usually
used to directly call a dispatching Claw operation:
Claw.Move (Get_Claw_Object (My_Button).all, <new location>);
Because the access returned is never used for more than a single subprogram,
we implemented the function with Unchecked_Access:
function Get_Claw_Object (Window : in Button_Type)
return Claw.Any_Window_Access_Type is
This code is illegal, of course, as Window.My_Button is a constant, and
Any_Window_Access_Type is an access-to-variable. Since Claw.Move takes an
in out parameter, changing Any_Window_Access_Type is out of the question.
Changing this to the "obvious" implementation:
function Get_Claw_Object (Window : access Button_Type)
return Claw.Any_Window_Access_Type is
means that calling objects have to be declared as aliased, and an additional
'Access used. Moreover, there is the run-time overhead of passing an
accessibility level, even though it will never be used in this case.
What we really want, of course, is to write:
function Get_Claw_Object (Window : in out Button_Type)
return Claw.Any_Window_Access_Type is
which we can now do.
Conceptually, of course, the parameter to this function isn't even modified.
We just need to use in out here to prevent someone from passing a constant,
which could cause all manner of trouble.
ACATS tests are needed to test that this is allowed, and that the restrictions
on operator symbols are enforced. Moreover, existing ACATS B-Test tests
prohibiting in out parameters on functions need to be withdrawn.
From: Randy Brukardt, February 15, 2009
Version /01 of this AI is almost identical to the final state of AI95-0323 (when
it was voted no action). The only changes were to incorporate one wording comment
and to add a bit of discussion about the technical issues that were mentioned by
Tucker (see the e-mail toward the end of AI95-0323).
I distinctly remember someone saying "thank goodness that we don't allow "in out"
parameters in functions" during some ARG discussion. I was unable to find that
in the minutes of any ARG meeting or in any AIs. I also spent quite a bit of time
reading old AIs about freezing and incomplete views to see if adding "in out"
parameters would break anything; I was unable to find any rules that would not work
in that context. It's quite possible that the rule under discussion was later
modified eliminating the problem, or perhaps it was never used at all. Or
maybe I just failed to find it.
From: Randy Brukardt, April 30, 2009
The accessibility subcommittee discussed this AI during its conference call today,
and it decided not to make the protected function change. The AI (now version /02)
was thus rewritten to remove this change and discuss the reasons why.
Questions? Ask the ACAA Technical Agent