5.5.3 Procedural Iterators
A
procedural_iterator
invokes a user-defined procedure, passing in the body of the enclosing
loop_statement
as a parameter of an anonymous access-to-procedure type, to allow the
loop body to be executed repeatedly as part of the invocation of the
user-defined procedure.
Syntax
parameter_association_with_box ::=
[
formal_parameter_selector_name => ] <>
Name Resolution Rules
Legality Rules
Static Semantics
In a procedural iterator,
the Parallel_Calls aspect (see
9.10.1) of
the loop body procedure is True if the reserved word
parallel
occurs in the corresponding loop statement, and False otherwise.
The following aspects
may be specified for a callable entity S that has exactly one
formal parameter of an anonymous access-to-subprogram type:
Allows_Exit
The Allows_Exit aspect is of type Boolean. The specified value shall
be static. The Allows_Exit aspect of an inherited primitive subprogram
is True if Allows_Exit is True either for the corresponding subprogram
of the progenitor type or for any other inherited subprogram that it
overrides. If not specified or inherited as True, the Allows_Exit aspect
of a callable entity is False. For an entry, only a confirming specification
of False is permitted for the Allows_Exit aspect.
Specifying the Allows_Exit aspect to be
True for a subprogram indicates that the subprogram
allows exit,
meaning that it is prepared to be completed by arbitrary transfers of
control from the loop body procedure, including propagation of exceptions.
A subprogram for which Allows_Exit is True should use finalization as
appropriate rather than exception handling to recover resources and make
any necessary final updates to data structures.
Parallel_Iterator
The Parallel_Iterator aspect is of type Boolean. The specified value
shall be static. The Parallel_Iterator aspect of an inherited primitive
subprogram is True if Parallel_Iterator is True either for the corresponding
subprogram of the progenitor type or for any other inherited subprogram
that it overrides. If not specified or inherited as True, the Parallel_Iterator
aspect of a callable entity is False.
Specifying the Parallel_Iterator aspect
to be True for a callable entity indicates that the entity is allowed
to invoke the loop body procedure from multiple distinct logical threads
of control. The Parallel_Iterator aspect for a subprogram shall be statically
False if the subprogram allows exit.
Legality Rules
If a callable entity overrides an inherited dispatching
subprogram that allows exit, the overriding callable entity also shall
allow exit. If a callable entity overrides an inherited dispatching subprogram
that has a True Parallel_Iterator aspect, the overriding callable entity
also shall have a True Parallel_Iterator aspect.
If the actual parameter of an anonymous access-to-subprogram
type, passed in an explicit call of a subprogram for which the Parallel_Iterator
aspect is True, is of the form
P'Access, the designated subprogram
P shall have a Parallel_Calls aspect True (see
9.10.1).
Dynamic Semantics
For the execution of a
loop_statement
with an
iteration_scheme
that has a
procedural_iterator,
the procedure denoted by the
name
or
prefix
of the
iterator_procedure_call
(the
iterating procedure)
is invoked, passing
an access value designating the loop body procedure as a parameter. The
iterating procedure then calls the loop body procedure zero or more times
and returns, whereupon the
loop_statement
is complete. If the
parallel reserved word is present, the iterating
procedure is allowed to invoke the loop body procedure from multiple
distinct logical threads of control. The
aspect_specification,
if any, is elaborated prior to the invocation of the iterating procedure.
Bounded (Run-Time) Errors
If the callable entity identified
in the
iterator_procedure_call
allows exit, then it is a bounded error for a call of the loop body procedure
to be performed from within an abort-deferred operation (see
9.8),
unless the entire
loop_statement
was within the same abort-deferred operation. If detected, Program_Error
is raised at the point of the call; otherwise, a transfer of control
from the
sequence_of_statements
of the
loop_statement
will not necessarily terminate the
loop_statement,
and the loop body procedure can be called again.
If a
loop_statement
with the
procedural_iterator
as its
iteration_scheme
(see
5.5) does not begin with the reserved
word
parallel, it is a bounded error if the loop body procedure
is invoked from a different logical thread of control than the one that
initiates the
loop_statement.
If detected, Program_Error is raised; otherwise, conflicts associated
with concurrent executions of the loop body procedure can occur without
being detected by the applicable conflict check policy (see
9.10.1).
Furthermore, propagating an exception or making an attempt to exit in
the presence of multiple threads of control will not necessarily terminate
the
loop_statement,
deadlock can occur, or the loop body procedure can be called again.
Examples
Example of iterating
over a map from My_Key_Type to My_Element_Type (see A.18.4):
for (C : Cursor) of My_Map.Iterate loop
Put_Line (My_Key_Type'Image (Key (C)) & " => " &
My_Element_Type'Image (Element (C)));
end loop;
-- The above is equivalent to:
declare
procedure P (C : Cursor) is
begin
Put_Line (My_Key_Type'Image (Key (c)) & " => " &
My_Element_Type'Image (Element (C)));
end P;
begin
My_Map.Iterate (P'Access);
end;
Example of iterating
over the environment variables (see A.17):
for (Name, Val) of Ada.Environment_Variables.Iterate(<>) loop
-- "(<>)" is optional because it is the last parameter
Put_Line (Name & " => " & Val);
end loop;
-- The above is equivalent to:
declare
procedure P (Name : String; Val : String) is
begin
Put_Line (Name & " => " & Val);
end P;
begin
Ada.Environment_Variables.Iterate (P'Access);
end;
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe