@@ -128,11 +128,61 @@ int foo();
128
128
129
129
$(H2 $(LNAME2 pure-functions, Pure Functions))
130
130
131
- $(P Pure functions are functions that cannot access global/static
132
- mutable state, except if their arguments contain pointers to such. This
133
- enables optimizations based on the fact that a pure function may at most
134
- mutate state reachable through its parameters. To that end, a pure
135
- function:)
131
+ $(P Pure functions are functions that cannot directly access global or static
132
+ mutable state. `pure` guarantees that a pure function call
133
+ won't access or modify any implicit state in the program.
134
+ )
135
+
136
+ $(P Unlike other functional programming languages, D's `pure`
137
+ functions allow modification of the caller state through their mutable
138
+ parameters.
139
+ )
140
+
141
+ ---
142
+ pure int foo(int[] arr) { arr[] += 1; return arr.length; }
143
+ int[] a = [1, 2, 3];
144
+ foo(a);
145
+ assert(a == [2, 3, 4]);
146
+ ---
147
+
148
+ $(P A `pure` function accepting parameters with mutable indirections offers
149
+ what's called "weak purity" because it can change program state
150
+ transitively through its arguments. A `pure` function that has
151
+ no parameter with mutable indirections is called "strongly pure"
152
+ and fulfills the purity definition in traditional functional languages.
153
+ Weakly `pure` functions are useful as reusable building blocks for strongly pure functions.
154
+ )
155
+
156
+ $(P To control mutations, D has the `immutable` type qualifier. If all of
157
+ a $(D pure) function's parameters are `immutable` or copied values
158
+ without any indirections, it can guarantee that the pure function has
159
+ no side effects.
160
+ )
161
+ $(P To prevent mutation, D offers the `immutable` type qualifier.
162
+ If all of a `pure` function's parameters are `immutable` or
163
+ copied values without any indirections (e.g. `int`),
164
+ the type system guarantees no side effects.
165
+ )
166
+
167
+ ---
168
+ struct S { double x; }
169
+ pure int foo(immutable(int)[] arr, int num, S val)
170
+ {
171
+ //arr[num] = 1; // compile error
172
+ num = 2; // has no side effect to the caller side
173
+ val.x = 3.14; // ditto
174
+ return arr.length;
175
+ }
176
+ ---
177
+
178
+ $(P The maximum guarantee of `pure` is called "strong purity". It can enable
179
+ optimizations based on the fact
180
+ that a function is guaranteed to not mutate anything which isn't passed to it.
181
+ For cases where the compiler can guarantee that a pure function cannot
182
+ alter its arguments, it can enable full, functional purity (i.e. the guarantee
183
+ that the function will always return the same result for the same arguments).
184
+ To that end, a pure function:
185
+ )
136
186
137
187
$(UL
138
188
$(LI does not read or write any global or static mutable state)
@@ -427,6 +477,35 @@ $(H2 $(LNAME2 inout-functions, Inout Functions))
427
477
be matched with inout.
428
478
)
429
479
480
+ $(P $(RELATIVE_LINK2 variadicnested, Nested functions) inside pure function are implicitly marked as pure.
481
+
482
+ ---
483
+ pure int foo(int x, immutable int y)
484
+ {
485
+ int bar()
486
+ // implicitly marked as pure, to be "weak purity"
487
+ // hidden context pointer is mutable
488
+ {
489
+ x = 10; // can access states in enclosing scope
490
+ // through the mutable context pointer
491
+ return x;
492
+ }
493
+ pragma(msg, typeof(&bar)); // int delegate() pure
494
+
495
+ int baz() immutable
496
+ // qualify hidden context pointer with immutable,
497
+ // and has no other parameters, make "strong purity"
498
+ {
499
+ //return x; // error, cannot access mutable data
500
+ // through the immutable context pointer
501
+ return y; // ok
502
+ }
503
+
504
+ // can call pure nested functions
505
+ return bar() + baz();
506
+ }
507
+ ---
508
+ )
430
509
431
510
$(H2 $(LNAME2 optional-parenthesis, Optional Parentheses))
432
511
@@ -2101,7 +2180,7 @@ void main()
2101
2180
2102
2181
$(H2 $(LNAME2 interpretation, Compile Time Function Execution (CTFE)))
2103
2182
2104
- $(P Functions which are both portable and free of side-effects can be
2183
+ $(P Functions which are both portable and free of global side-effects can be
2105
2184
executed at compile time. This is useful when constant folding
2106
2185
algorithms need to include recursion and looping. Compile time function
2107
2186
execution is subject to the following restrictions:
@@ -2169,7 +2248,7 @@ $(H2 $(LNAME2 interpretation, Compile Time Function Execution (CTFE)))
2169
2248
)
2170
2249
2171
2250
$(LI
2172
- Any pointer may be cast to $(D void *) and from $(D void *) back to
2251
+ Any pointer may be cast to $(D void*) and from $(D void*) back to
2173
2252
its original type. Casting between pointer and non-pointer types is
2174
2253
prohibited.
2175
2254
)
@@ -2188,7 +2267,7 @@ int countTen(int x)
2188
2267
return x;
2189
2268
}
2190
2269
2191
- static assert(countTen(6) == 6); // OK
2270
+ static assert(countTen(6) == 6); // OK
2192
2271
static assert(countTen(12) == 12); // invalid, modifies y.
2193
2272
---
2194
2273
$(P The $(D __ctfe) boolean pseudo-variable, which evaluates to $(D_KEYWORD true)
@@ -2205,7 +2284,7 @@ static assert(countTen(12) == 12); // invalid, modifies y.
2205
2284
example:)
2206
2285
2207
2286
$(UL
2208
- $(LI initialization of a static variable)
2287
+ $(LI initialization of a static variable or a manifest constant )
2209
2288
$(LI dimension of a static array)
2210
2289
$(LI argument for a template value parameter)
2211
2290
)
@@ -2224,9 +2303,9 @@ int square(int i)
2224
2303
2225
2304
void foo()
2226
2305
{
2227
- static j = square(3); // compile time
2306
+ static j = square(3); // compile time
2228
2307
writeln(j);
2229
- writeln(square(4)); // run time
2308
+ writeln(square(4)); // run time
2230
2309
writeln(eval!(square(5))); // compile time
2231
2310
}
2232
2311
---
@@ -2279,6 +2358,84 @@ const int x = foo("1");
2279
2358
generated. A function template would be the appropriate
2280
2359
method to implement this sort of thing.)
2281
2360
2361
+ $(H3 $(LNAME2 nogc-functions, No-GC Functions))
2362
+
2363
+ $(P No-GC functions are functions marked with the $(D @nogc) attribute.
2364
+ Those functions do not allocate memory on the GC heap,
2365
+ through the following language features:
2366
+ )
2367
+
2368
+ $(UL
2369
+ $(LI $(DDSUBLINK expression, ArrayLiteral, constructing an array) on the heap)
2370
+ $(LI resizing an array by writing to its $(D .length) property)
2371
+ $(LI array $(DDSUBLINK expression, CatExpression, concatenation) and appending)
2372
+ $(LI $(DDSUBLINK expression, AssocArrayLiteral, constructing an associative array) on the heap)
2373
+ $(LI $(DDSUBLINK expression, IndexExpression, indexing) an associative array
2374
+ (because it may throw $(D RangeError) if the specified key is not present))
2375
+ $(LI $(DDSUBLINK expression, NewExpression, allocating an object) on the heap)
2376
+ $(LI $(DDSUBLINK expression, DeleteExpression, deleting an object) on the heap)
2377
+ )
2378
+
2379
+ ---
2380
+ @nogc void foo()
2381
+ {
2382
+ auto a = ['a']; // error, allocates
2383
+ a.length = 1; // error, array resizing allocates
2384
+ a = a ~ a; // error, arrays concatenation allocates
2385
+ a ~= 'c'; // error, appending to arrays allocates
2386
+
2387
+ auto aa = ["x":1]; // error, allocates
2388
+ aa["abc"]; // error, indexing may allocate and throws
2389
+
2390
+ auto p = new int; // error, operator new allocates
2391
+ delete p; // error, operator delete deallocates
2392
+ }
2393
+ ---
2394
+
2395
+ $(P No-GC functions cannot call functions that are not $(D @nogc).
2396
+ )
2397
+
2398
+ ---
2399
+ @nogc void foo()
2400
+ {
2401
+ bar(); // error, bar() may allocate
2402
+ }
2403
+
2404
+ void bar() { }
2405
+ ---
2406
+
2407
+ $(P No-GC functions cannot be closures.
2408
+ )
2409
+
2410
+ ---
2411
+ @nogc int delegate() foo()
2412
+ {
2413
+ int n; // error, variable n cannot be allocated on heap
2414
+ return (){ return n; }
2415
+ }
2416
+ ---
2417
+
2418
+ $(P $(D @nogc) affects the type of the function. A $(D @nogc)
2419
+ function is covariant with a non-$(D @nogc) function.
2420
+ )
2421
+
2422
+ ---
2423
+ void function() fp;
2424
+ void function() @nogc gp; // pointer to @nogc function
2425
+
2426
+ void foo();
2427
+ @nogc void bar();
2428
+
2429
+ void test()
2430
+ {
2431
+ fp = &foo; // ok
2432
+ fp = &bar; // ok, it's covariant
2433
+ gp = &foo; // error, not contravariant
2434
+ gp = &bar; // ok
2435
+ }
2436
+ ---
2437
+
2438
+
2282
2439
$(H2 $(LNAME2 function-safety, Function Safety))
2283
2440
2284
2441
$(P $(I Safe functions) are functions that are statically checked
@@ -2312,6 +2469,10 @@ $(H3 $(LNAME2 safe-functions, Safe Functions))
2312
2469
$(LI Cannot access $(D __gshared) variables.)
2313
2470
)
2314
2471
2472
+ $(P When indexing and slicing an array, an out of bounds access
2473
+ will cause a runtime error, in order to prevent undefined behavior.
2474
+ )
2475
+
2315
2476
$(P Functions nested inside safe functions default to being
2316
2477
safe functions.
2317
2478
)
@@ -2361,8 +2522,8 @@ $(H2 $(LNAME2 function-attribute-inference, Function Attribute Inference))
2361
2522
$(RELATIVE_LINK2 pure-functions, $(D pure)),
2362
2523
$(RELATIVE_LINK2 nothrow-functions, $(D nothrow)),
2363
2524
$(RELATIVE_LINK2 safe-functions, $(D @safe)), and
2364
- $(LINK2 attribute.html# nogc, $(D @nogc)) attributes unless
2365
- specifically overridden.
2525
+ $(RELATIVE_LINK2 nogc-functions , $(D @nogc))
2526
+ attributes unless specifically overridden.
2366
2527
)
2367
2528
2368
2529
$(P Attribute inference is not done for other functions, even if the function
0 commit comments