forked from DlangRen/Programming-in-D
-
Notifications
You must be signed in to change notification settings - Fork 0
/
scope.d
142 lines (104 loc) · 3.99 KB
/
scope.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
Ddoc
$(DERS_BOLUMU $(IX scope(success)) $(IX scope(exit)) $(IX scope(failure)) $(CH4 scope))
$(P
As we have seen in the previous chapter, expressions that must always be executed are written in the $(C finally) block, and expressions that must be executed when there are error conditions are written in $(C catch) blocks.
)
$(P
We can make the following observations about the use of these blocks:
)
$(UL
$(LI $(C catch) and $(C finally) cannot be used without a $(C try) block.)
$(LI Some of the variables that these blocks need may not be accessible within these blocks:
---
void foo(ref int r) {
try {
$(HILITE int addend) = 42;
r += addend;
mayThrow();
} catch (Exception exc) {
r -= addend; $(DERLEME_HATASI)
}
}
---
$(P
That function first modifies the reference parameter and then reverts this modification when an exception is thrown. Unfortunately, $(C addend) is accessible only in the $(C try) block, where it is defined. $(I ($(B Note:) This is related to name scopes, as well as object lifetimes, which will be explained in $(LINK2 /ders/d.en/lifetimes.html, a later chapter.)))
)
)
$(LI Writing all of potentially unrelated expressions in the single $(C finally) block at the bottom separates those expressions from the actual code that they are related to.
)
)
$(P
The $(C scope) statements have similar functionality with the $(C catch) and $(C finally) scopes but they are better in many respects. Like $(C finally), the three different $(C scope) statements are about executing expressions when leaving scopes:
)
$(UL
$(LI $(C scope(exit)): the expression is always executed when exiting the scope, regardless of whether successfully or due to an exception)
$(LI $(C scope(success)): the expression is executed only if the scope is being exited successfully)
$(LI $(C scope(failure)): the expression is executed only if the scope is being exited due to an exception)
)
$(P
Although these statements are closely related to exceptions, they can be used without a $(C try-catch) block.
)
$(P
As an example, let's write the function above with a $(C scope(failure)) statement:
)
---
void foo(ref int r) {
int addend = 42;
r += addend;
$(HILITE scope(failure)) r -= addend;
mayThrow();
}
---
$(P
The $(C scope(failure)) statement above ensures that the $(C r -= addend) expression will be executed if the function's scope is exited due to an exception. A benefit of $(C scope(failure)) is the fact that the expression that reverts another expression is written close to it.
)
$(P
$(C scope) statements can be specified as blocks as well:
)
---
scope(exit) {
// ... expressions ...
}
---
$(P
Here is another function that tests all three of these statements:
)
---
void test() {
scope(exit) writeln("when exiting 1");
scope(success) {
writeln("if successful 1");
writeln("if successful 2");
}
scope(failure) writeln("if thrown 1");
scope(exit) writeln("when exiting 2");
scope(failure) writeln("if thrown 2");
throwsHalfTheTime();
}
---
$(P
If no exception is thrown, the output of the function includes only the $(C scope(exit)) and $(C scope(success)) expressions:
)
$(SHELL
when exiting 2
if successful 1
if successful 2
when exiting 1
)
$(P
If an exception is thrown, the output includes the $(C scope(exit)) and $(C scope(failure)) expressions:
)
$(SHELL
if thrown 2
when exiting 2
if thrown 1
when exiting 1
object.Exception@...: the error message
)
$(P
As seen in the outputs, the blocks of the $(C scope) statements are executed in reverse order. This is because later code may depend on previous variables. Executing the $(C scope) statements in reverse order enables undoing side effects of earlier expressions in a consistent order.
)
Macros:
SUBTITLE=scope
DESCRIPTION=The scope(success), scope(failure), and scope(exit) statements that are used for specifying expressions that must be executed when exiting scopes.
KEYWORDS=d programming language tutorial book scope