Skip to content

Commit 0c18437

Browse files
authored
Merge pull request #3192 from ntrel/opApply
[spec/statement.dd] Improve opApply docs Signed-off-by: Dennis <[email protected]> Merged-on-behalf-of: Dennis <[email protected]>
2 parents b85173c + 9dcd605 commit 0c18437

File tree

1 file changed

+47
-38
lines changed

1 file changed

+47
-38
lines changed

spec/statement.dd

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ $(H3 $(LNAME2 foreach_over_struct_and_classes, Foreach over Structs and Classes
675675
special $(LEGACY_LNAME2 opApply, op-apply, $(D opApply)) member function, and the
676676
`foreach_reverse` behavior is defined by the special
677677
$(LEGACY_LNAME2 opApplyReverse, op-apply-reverse, $(D opApplyReverse)) member function.
678-
These functions have the type:
678+
These functions have the signatures:
679679
)
680680

681681
--------------
@@ -684,21 +684,27 @@ $(H3 $(LNAME2 foreach_over_struct_and_classes, Foreach over Structs and Classes
684684
int opApplyReverse(scope int delegate(ref Type [, ...]) dg);
685685
--------------
686686

687-
$(P where $(I Type) matches the $(I Type) used in the $(I ForeachType)
688-
declaration of $(I Identifier). Multiple $(I ForeachType)s
689-
correspond with multiple $(I Type)s in the delegate type
690-
passed to $(D opApply) or $(D opApplyReverse).
691-
There can be multiple $(D opApply) and $(D opApplyReverse) functions,
687+
$(P where $(I Type) determines the type of the first $(GLINK ForeachType)
688+
declared. Multiple $(I ForeachType)s are supported.
689+
Each one must match a parameter of the delegate *dg*,
690+
otherwise the *ForeachStatement* will cause an error.)
691+
692+
$(P There can be multiple $(D opApply) and $(D opApplyReverse) functions -
692693
one is selected
693-
by matching the type of $(I dg) to the $(I ForeachType)s
694-
of the $(I ForeachStatement).
695-
The body of the apply
696-
function iterates over the elements it aggregates, passing them
697-
each to the $(I dg) function. If the $(I dg) returns 0, then
698-
apply goes on to the next element.
699-
If the $(I dg) returns a nonzero value, apply must cease
700-
iterating and return that value. Otherwise, after done iterating
701-
across all the elements, apply will return 0.
694+
by matching each parameter type of *dg* to the type of each $(I ForeachType)
695+
declared in the $(I ForeachStatement).)
696+
697+
$(P The body of the apply
698+
function iterates over the elements it aggregates, passing each one
699+
in successive calls to the $(I dg) delegate. The delegate return value
700+
determines whether to interrupt iteration:)
701+
702+
$(UL
703+
$(LI If the result is nonzero, apply must cease
704+
iterating and return that value.)
705+
$(LI If the result is 0, then iteration should continue.
706+
If there are no more elements to iterate,
707+
apply must return 0.)
702708
)
703709

704710
$(P For example, consider a class that is a container for two elements:)
@@ -711,25 +717,22 @@ $(H3 $(LNAME2 foreach_over_struct_and_classes, Foreach over Structs and Classes
711717

712718
int opApply(scope int delegate(ref uint) dg)
713719
{
714-
int result = 0;
715-
716720
foreach (e; array)
717721
{
718-
result = dg(e);
722+
int result = dg(e);
719723
if (result)
720-
break;
724+
return result;
721725
}
722-
return result;
726+
return 0;
723727
}
724728
}
725729

726730
void main()
727731
{
728732
import std.stdio;
729-
Foo a = new Foo();
730733

731-
a.array[0] = 73;
732-
a.array[1] = 82;
734+
Foo a = new Foo();
735+
a.array = [73, 82];
733736

734737
foreach (uint u; a)
735738
{
@@ -745,34 +748,44 @@ $(CONSOLE
745748
73
746749
82
747750
)
748-
$(P The `scope` storage class on the $(I dg) parameter means that the parameter's value does
749-
not escape the scope of the $(I opApply) function (an example would be assigning $(I dg) to a
750-
global). If it cannot be statically guaranteed that $(I dg) does not escape, a closure may
751+
$(P The `scope` storage class on the $(I dg) parameter means that the delegate does
752+
not escape the scope of the $(D opApply) function (an example would be assigning $(I dg) to a
753+
global variable). If it cannot be statically guaranteed that $(I dg) does not escape, a closure may
751754
be allocated for it on the heap instead of the stack.
752755
)
753756

754757
$(BEST_PRACTICE Annotate delegate parameters to `opApply` functions with `scope` when possible.)
755758

756-
$(P $(LEGACY_LNAME2 opApply, op-apply, $(I opApply)) can also be a templated function,
757-
which will infer the types of parameters based on the $(I ForeachStatement).
758-
)
759+
$(P $(B Important:) If $(D opApply) catches any exceptions, ensure that those
760+
exceptions did not originate from the delegate passed to $(D opApply). The user would expect
761+
exceptions thrown from a `foreach` body to both terminate the loop, and propagate outside
762+
the `foreach` body.
763+
)
759764

760-
$(P For example:)
765+
$(H4 $(LNAME2 template-op-apply, Template `opApply`))
761766

767+
$(P $(D opApply) can also be a templated function,
768+
which will infer the types of parameters based on the $(I ForeachStatement).
769+
For example:)
770+
771+
$(SPEC_RUNNABLE_EXAMPLE_RUN
762772
--------------
763773
struct S
764774
{
765775
import std.traits : ParameterTypeTuple; // introspection template
776+
import std.stdio;
766777

767778
int opApply(Dg)(scope Dg dg)
768779
if (ParameterTypeTuple!Dg.length == 2) // foreach with 2 parameters
769780
{
781+
writeln(2);
770782
return 0;
771783
}
772784

773785
int opApply(Dg)(scope Dg dg)
774-
if (ParameterTypeTuple!Dg.length == 3) // foreach with takes 3 parameters
786+
if (ParameterTypeTuple!Dg.length == 3) // foreach with 3 parameters
775787
{
788+
writeln(3);
776789
return 0;
777790
}
778791
}
@@ -783,12 +796,7 @@ $(CONSOLE
783796
foreach (int a, int b, float c; S()) { } // calls second opApply function
784797
}
785798
--------------
786-
787-
$(P It is important to make sure that, if $(D opApply) catches any exceptions, that those
788-
exceptions did not originate from the delegate passed to $(I opApply). The user would expect
789-
exceptions thrown from a `foreach` body to both terminate the loop, and propagate outside
790-
the `foreach` body.
791-
)
799+
)
792800

793801
$(H3 $(LEGACY_LNAME2 foreach_with_ranges, foreach-with-ranges, Foreach over Structs and Classes with Ranges))
794802

@@ -946,7 +954,8 @@ $(H4 $(LNAME2 front-seq, Multiple Element Values))
946954
$(H3 $(LNAME2 foreach_over_delegates, Foreach over Delegates))
947955

948956
$(P If $(I ForeachAggregate) is a delegate, the type signature of
949-
the delegate is of the same as for $(D opApply). This enables
957+
the delegate is of the same as for
958+
$(RELATIVE_LINK2 foreach_over_struct_and_classes, opApply). This enables
950959
many different named looping strategies to coexist in the same
951960
class or struct.)
952961

0 commit comments

Comments
 (0)