Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Differences when using anonymous access procedures or access procedure types

Tags:

scope

nested

ada

I've been working with Ada for a bit over a year, and while I think I've got the hang of it and feel comfortable with the very strong type system, I run into troubles once in a while.

At the moment, I have an issue regarding nested procedures in which the compiler gives me an error which I do not really can wrap my head around: subprogram must not be deeper than access type. This error arises when I've declared a type which is an access to a procedure, however it works flawlessly when using an anonymous access parameter, as shown in the following MWE:

procedure Generaltest is
   type T_Access_Procedure is access procedure;

   procedure Test_Access (Proc : access procedure) is
   begin
      null;
   end Test_Access;

   procedure Test_Type (Proc : in T_Access_Procedure) is
   begin
      null;
   end Test_Type;

   procedure Test is
      procedure Nested_Procedure is
      begin
         null;
      end;

      -- Not allowed; subprogram must not bee deeper than access procedure.
      Proc : T_Access_Procedure := Nested_Procedure'Access;

   begin
      Test_Access (Nested_Procedure'Access); -- This line works fine.
      Test_Type (Nested_Procedure'Access);   -- This line also generates the error.
   end Test;

begin
   Test;
end Generaltest;

From my point of view, this can be interpreted in two different ways, depending on the emphasis; the subprogram must not be deeper than access type or, the subprogram must not be deeper than access type. In other words, is the error regarding the subprogram itself, or the type of the parameter? I tend to believe it is the former as the subprogram is an access type, but I'm definitely not sure.

Can someone explain to me what is the real difference between using the type as in parameter or using an access parameter in this sence and why the former is thought to be "deeper"?

In my world using the type T_Access_Procedure as an in paramater is a more elegant way of doing it, especially if my procedure of choice is to be used in many procedures or if it have a long argument list.

like image 357
chrillof Avatar asked Jun 17 '20 20:06

chrillof


2 Answers

As discussed in Ada 95 Rationale, 3.7.2 Access to Subprograms, "Compile-time accessibility rules ensure that a subprogram designated by an access value cannot be called after its enclosing scope has exited." In your example, an access value referencing Nested_Procedure is only valid within the scope of Test, but a value of type T_Access_Procedure could be used to invoke Nested_Procedure outside the scope of Test. Both Proc and the actual parameter passed to Test_Type are of type T_Access_Procedure; neither is permitted.

A specific alternative depends on what you want to do. It may be helpful to look at Rationale for Ada 2012, 6.3 Iteration. As discussed here, "Generic formal subprograms remain the most general means of parameterizing an algorithm by an arbitrary externally specified subprogram."

like image 64
trashgod Avatar answered Nov 11 '22 10:11

trashgod


The difference is deliberate. As trashgod has explained, with a named access type, it is possible to store the access value and call it later, and the rules are intended to prevent storing a value that might otherwise be called when it is invalid. Anonymous access-to-subprogram parameters, on the other hand, cannot be stored, which allows passing any subprogram.

like image 32
Jeffrey R. Carter Avatar answered Nov 11 '22 10:11

Jeffrey R. Carter