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.
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."
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With