Version 1.2 of ai05s/ai05-0140-1.txt

Unformatted version of ai05s/ai05-0140-1.txt version 1.2
Other versions for file ai05s/ai05-0140-1.txt

!standard 5.5          09-03-06 AI05-0140-1/02
!class Amendment 09-02-13
!status No Action (8-0-0) 09-02-22
!status work item 09-02-13
!status received 09-01-19
!priority Medium
!difficulty Medium
!subject Identity functions
!summary
(See proposal.)
!problem
When creating an interface, procedures can be given a default interface that does nothing. However, there is no corresponding capability for functions, which means its always necessary to override a function declared in an interface, even when the function does nothing other than return a parameter.
This omission means that designs are pushed into using procedures for routines that would rarely be overridden, even if a function is a more appropriate
!proposal
Add identity functions with new syntax:
function Dereference (Pool : in out Root_Storage_Pool; Access_Value : in Address) return Address is (Access_Value);
The parenthesized parameter name must have a type that statically matches the subtype of the function result.
!wording
** TBD **
!discussion
A way to think of identity functions (and null procedures for that matter) is that they provide a default implementation for an interface.
Note that the parameter returned can't be of the interface type (it doesn't have any information to be returnable). That follows from the static matching rule and the rules against functions that return an abstract type.
We'd probably want to consider an identity function default for generic formal subprograms as well.
An alternative to the plain parenthesized expression would be to add a new keyword to make it crystal-clear that an identity function is being defined.
function Dereference (Pool : in out Root_Storage_Pool; Access_Value : in Address) return Address is identity (Access_Value);
That seems especially important if we are using this as a default for generic formal subprograms:
function Fooey (Value : in Natural) return Natural is (Value); -- Identity function default. function Fooey (Value : in Natural) return Natural is Value; -- A function named Value is the default.
Another alternative would be to make this a regular simple return statement:
function Dereference (Pool : in out Root_Storage_Pool; Access_Value : in Address) return Address is return Access_Value;
allowing an expression of the parameters (thus allowing type conversions and the like). But that seems like it would be opening a can of worms.
!examples
!ACATS test
!appendix

From: Randy Brukardt
Date: Monday, January 19, 2009  9:20 PM

Following is one of a number of "trial-balloon" proposals for future
enhancements to Ada.

[This is version /01 of the AI - ED.]

****************************************************************

From: Niklas Holsti
Date: Tuesday, January 20, 2009  2:19 AM

A small comment on Randy's syntax for identity functions:

> The closest analog to null procedures is identity functions...
>
> Thus, one could imagine defining a way to define identity functions.
> These are unfortunately more complex than null procedures, because of
> the need to identify the parameter that is the one returned. So, we've
> have to add something like:
>
> function Dereference (Pool : in out Root_Storage_Pool;
>                       Access_Value : in Address) return Address is
> identity (2);
>
> which means that the function is an identity function on the second
> parameter.

Rather than giving the parameter number, I would prefer to give the name of the
parameter to be returned, and even omit the new "identity" keyword:

    function Dereference (Pool : in out Root_Storage_Pool;
                          Access_Value : in Address)
    return Address is Access_Value;

This seems both more readable and more robust towards changes in the parameter
list.

****************************************************************

From: Dmitry A. Kazakov
Date: Tuesday, January 20, 2009  2:00 PM

> This seems both more readable and more robust towards changes in the
> parameter list.

I think it would be wrong as well as the Randy proposal, though for different
reasons.

   function Foo (...) return ... is <implementation>;

in fact provides an implementation for Foo. Presently we have special
implementations:

1." is abstract" denotes no implementation 2. "is null" denotes null body 3.
"renames <Name>" denotes the body of <Name>

Apart for that renames obviously should be "is <Name>", first two are
inconsistent with:

1. Separation of specification and implementation. They shall not be allowed in
the package specification.

2. "is null" is inconsistent with the notion of interface. Interface may not
have implementations. From this point of view the thing Randy proposes breaks it
further. I don't care much about it, because the notion of interface type is
rubbish, but introducing rubbish in the first place one should try to uphold it.
(:-))

Returning to your proposal, it is wrong because <parameter-name> does not look
like a body. A body is a literal of some procedural type. From this point of
view Randy's identity is a function-valued function, that takes an argument and
produces a body. Granted, it should better be

   Lambda (Access_Value)

or better

   Access_Value'Lambda

and Identity (X) should better mean

   begin return X; end

so, for example:

   type Group is ...
   function Zero (X : Group) return Element is Identity (0);
   function One (X : Group)  return Element is Identity (1);

or

   type Linked_List_Element is ...;
   function Next (L : Linked_List_Element)
      return access Linked_List_Element is Identity (null);

Surely once you introduce this stuff you should also allow type conversion:

   type Linked_List_Element is ...;
   function Foo (X :String) return Unbounded_String is
      To_Unbounded_String (X'Lambda);

Which is technically a composition:

   To_Unbounded_String o X'Lambda

And also allow it as closures:

   procedure Inverse (A : in out Vector) is
   begin
      Update (A, -X'Lambda);
   end Inverse;

Instead of

   procedure Inverse (A : in out Vector) is
      function Update_Element (X :Element) return Element is
      begin
          return -X;
      end Update_Element;
   begin
      Update (A, Update_Element'Access);
   end Inverse;

I hope it is clear where it goes...

****************************************************************

Questions? Ask the ACAA Technical Agent