使用匿名访问过程或访问过程类型时的差异
Differences when using anonymous access procedures or access procedure types
我已经使用 Ada 一年多了,虽然我认为我已经掌握了它的窍门并且对非常强大的类型系统感到满意,但我 运行 遇到过一次麻烦一会儿。
目前,我有一个关于嵌套过程的问题,其中编译器给我一个错误,我真的无法理解:subprogram must not be deeper than access type
。当我声明了一个可以访问过程的类型时会出现此错误,但是在使用匿名访问参数时它可以完美地工作,如下面的 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;
从我的角度来看,这可以用两种不同的方式来解释,这取决于重点; 子程序不能比访问类型更深,或者,子程序不能比访问类型更深。也就是说,是子程序本身的错误,还是参数类型的错误?我倾向于认为是前者,因为子程序是访问类型,但我不确定。
有人可以向我解释在参数中使用类型或在这个意义上使用访问参数之间的真正区别是什么,以及为什么前者被认为是 "deeper"?
在我的世界中,使用类型 T_Access_Procedure
作为 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." 在您的示例中,引用 Nested_Procedure
的访问值仅在 范围内有效 =11=],但类型 T_Access_Procedure
的值可用于在 Test
的范围 之外调用 Nested_Procedure
。 Proc
和传给Test_Type
的实参都是T_Access_Procedure
类型;两者都是不允许的。
具体的替代方案取决于您想做什么。查看 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."
可能会有所帮助
差异是故意的。正如 trashgod 所解释的那样,使用命名的访问类型,可以存储访问值并在以后调用它,并且规则旨在防止存储可能在无效时调用的值。另一方面,匿名访问子程序参数不能存储,允许传递任何子程序。
我已经使用 Ada 一年多了,虽然我认为我已经掌握了它的窍门并且对非常强大的类型系统感到满意,但我 运行 遇到过一次麻烦一会儿。
目前,我有一个关于嵌套过程的问题,其中编译器给我一个错误,我真的无法理解:subprogram must not be deeper than access type
。当我声明了一个可以访问过程的类型时会出现此错误,但是在使用匿名访问参数时它可以完美地工作,如下面的 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;
从我的角度来看,这可以用两种不同的方式来解释,这取决于重点; 子程序不能比访问类型更深,或者,子程序不能比访问类型更深。也就是说,是子程序本身的错误,还是参数类型的错误?我倾向于认为是前者,因为子程序是访问类型,但我不确定。
有人可以向我解释在参数中使用类型或在这个意义上使用访问参数之间的真正区别是什么,以及为什么前者被认为是 "deeper"?
在我的世界中,使用类型 T_Access_Procedure
作为 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." 在您的示例中,引用 Nested_Procedure
的访问值仅在 范围内有效 =11=],但类型 T_Access_Procedure
的值可用于在 Test
的范围 之外调用 Nested_Procedure
。 Proc
和传给Test_Type
的实参都是T_Access_Procedure
类型;两者都是不允许的。
具体的替代方案取决于您想做什么。查看 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."
可能会有所帮助差异是故意的。正如 trashgod 所解释的那样,使用命名的访问类型,可以存储访问值并在以后调用它,并且规则旨在防止存储可能在无效时调用的值。另一方面,匿名访问子程序参数不能存储,允许传递任何子程序。