| 228 | | Returns $(D true) if $(D R) is an output range. An output range can be |
|---|
| 229 | | defined in three ways. |
|---|
| 230 | | |
|---|
| 231 | | $(OL |
|---|
| 232 | | |
|---|
| 233 | | $(LI $(D R) might define the primitive $(D put) that accepts an object |
|---|
| 234 | | convertible to $(D E). The following code should compile for such an |
|---|
| 235 | | output range: |
|---|
| 236 | | |
|---|
| 237 | | ---- |
|---|
| 238 | | R r; |
|---|
| 239 | | E e; |
|---|
| 240 | | r.put(e); // can write an element to the range |
|---|
| 241 | | ---- |
|---|
| 242 | | |
|---|
| 243 | | The semantics of $(D r.put(e)) an output range (not checkable during |
|---|
| 244 | | compilation) are assumed to output $(D e) to $(D r) and advance to the |
|---|
| 245 | | next position in $(D r), such that successive calls to $(D r.put) add |
|---|
| 246 | | extra elements to $(D r).) |
|---|
| 247 | | |
|---|
| 248 | | $(LI An input range with assignable elements is also an output |
|---|
| 249 | | range. In that case, inserting elements into the range is effected |
|---|
| 250 | | with two primitive calls: $(D r.front = e, r.popFront()). Such a range |
|---|
| 251 | | functions for output only as long as it is not empty.) |
|---|
| 252 | | |
|---|
| 253 | | ---- |
|---|
| 254 | | R r; |
|---|
| 255 | | E e; |
|---|
| 256 | | r.front = e; // can write an element to the range |
|---|
| 257 | | ---- |
|---|
| 258 | | |
|---|
| 259 | | $(LI Any $(D function) or $(D delegate) accepting arrays of $(D E) as |
|---|
| 260 | | input is also a valid output range.)) |
|---|
| 261 | | |
|---|
| 262 | | To write elements to either kind of output range, call the free |
|---|
| 263 | | function $(D put(r, e)) defined below. That function takes the |
|---|
| 264 | | appropriate cource of action depending on the range's kind. |
|---|
| 265 | | */ |
|---|
| 266 | | template isOutputRange(R, E) |
|---|
| 267 | | { |
|---|
| 268 | | enum bool isOutputRange = is(typeof( |
|---|
| 269 | | { |
|---|
| 270 | | R r; |
|---|
| 271 | | E e; |
|---|
| 272 | | r.put(e); // can write element to range |
|---|
| 273 | | }())) |
|---|
| 274 | | || |
|---|
| 275 | | isInputRange!R && is(typeof( |
|---|
| 276 | | { |
|---|
| 277 | | R r; |
|---|
| 278 | | E e; |
|---|
| 279 | | r.front = e; // can assign to the front of range |
|---|
| 280 | | }())) |
|---|
| 281 | | || |
|---|
| 282 | | is(typeof( |
|---|
| 283 | | { |
|---|
| 284 | | R r; |
|---|
| 285 | | E[] es; |
|---|
| 286 | | r(es); |
|---|
| 287 | | }())); |
|---|
| 288 | | } |
|---|
| 289 | | |
|---|
| 290 | | /** |
|---|
| 291 | | Outputs $(D e) to $(D r), which must be an output range. Depending on |
|---|
| 292 | | the range's kind, it evaluates one of the following: |
|---|
| 293 | | |
|---|
| 294 | | $(OL |
|---|
| 295 | | |
|---|
| 296 | | $(LI If $(D R) defines $(D put), then output is effected by evaluating |
|---|
| 297 | | $(D r.put(e)).) |
|---|
| 298 | | |
|---|
| 299 | | $(LI Else if $(D R) is an input range with assignable front, then |
|---|
| 300 | | output is effected by evaluating $(D (r.front = e, r.popFront())).) |
|---|
| 301 | | |
|---|
| 302 | | $(LI Else if $(D R) is a function type, a delegate type, or a type |
|---|
| 303 | | defining $(D opCall), then output is effected by evaluating $(D |
|---|
| 304 | | r(e)).) |
|---|
| 305 | | */ |
|---|
| 306 | | void put(R, E)(ref R r, E e) if (isOutputRange!(R, E)) |
|---|
| 307 | | { |
|---|
| 308 | | static if (!isArray!R && is(typeof(r.put(e)))) |
|---|
| 309 | | { |
|---|
| 310 | | r.put(e); |
|---|
| 311 | | } |
|---|
| 312 | | else static if (isInputRange!R && is(typeof(r.front = e))) |
|---|
| 313 | | { |
|---|
| 314 | | r.front = e; |
|---|
| 315 | | r.popFront(); |
|---|
| 316 | | } |
|---|
| 317 | | else static if (isArray!E && is(typeof(r(e)))) |
|---|
| 318 | | { |
|---|
| 319 | | r(e); |
|---|
| 320 | | } |
|---|
| 321 | | else static if (is(typeof(r(new E[])))) |
|---|
| 322 | | { |
|---|
| 323 | | r((&e)[0 .. 1]); |
|---|
| | 228 | Outputs $(D e) to $(D r). The exact effect is dependent upon the two |
|---|
| | 229 | types. which must be an output range. Several cases are accepted, as |
|---|
| | 230 | described below. The code snippets are attempted in order, and the |
|---|
| | 231 | first to compile "wins" and gets evaluated. |
|---|
| | 232 | |
|---|
| | 233 | $(BOOKTABLE , |
|---|
| | 234 | |
|---|
| | 235 | $(TR $(TH Code Snippet) $(TH Scenario)) |
|---|
| | 236 | |
|---|
| | 237 | $(TR $(TD $(D r.put(e);)) $(TD $(D R) specifically defines a method |
|---|
| | 238 | $(D put) accepting an $(D E).)) |
|---|
| | 239 | |
|---|
| | 240 | $(TR $(TD $(D r.put([ e ]);)) $(TD $(D R) specifically defines a |
|---|
| | 241 | method $(D put) accepting an $(D E[]).)) |
|---|
| | 242 | |
|---|
| | 243 | $(TR $(TD $(D r.front = e; r.popFront();)) $(TD $(D R) is an input |
|---|
| | 244 | range and $(D e) is assignable to $(D r.front).)) |
|---|
| | 245 | |
|---|
| | 246 | $(TR $(TD $(D for (; !e.empty; e.popFront()) put(r, e.front);)) $(TD |
|---|
| | 247 | Copying range $(D E) to range $(D R).)) |
|---|
| | 248 | |
|---|
| | 249 | $(TR $(TD $(D r(e);)) $(TD $(D R) is e.g. a delegate accepting an $(D |
|---|
| | 250 | E).)) |
|---|
| | 251 | |
|---|
| | 252 | $(TR $(TD $(D r([ e ]);)) $(TD $(D R) is e.g. a $(D delegate) |
|---|
| | 253 | accepting an $(D E[]).)) |
|---|
| | 254 | |
|---|
| | 255 | ) |
|---|
| | 256 | */ |
|---|
| | 257 | void put(R, E)(ref R r, E e) |
|---|
| | 258 | { |
|---|
| | 259 | static if (hasMember!(R, "put")) |
|---|
| | 260 | { |
|---|
| | 261 | // commit to using the "put" method |
|---|
| | 262 | static if (!isArray!R && is(typeof(r.put(e)))) |
|---|
| | 263 | { |
|---|
| | 264 | r.put(e); |
|---|
| | 265 | } |
|---|
| | 266 | else static if (!isArray!R && is(typeof(r.put((&e)[0..1])))) |
|---|
| | 267 | { |
|---|
| | 268 | r.put((&e)[0..1]); |
|---|
| | 269 | } |
|---|
| 337 | | void put(int); |
|---|
| 338 | | } |
|---|
| 339 | | static assert(isOutputRange!(B, int)); |
|---|
| 340 | | static assert(isOutputRange!(int[], int)); |
|---|
| | 312 | void put(int) {} |
|---|
| | 313 | } |
|---|
| | 314 | B b; |
|---|
| | 315 | put(b, 5); |
|---|
| | 316 | } |
|---|
| | 317 | |
|---|
| | 318 | unittest |
|---|
| | 319 | { |
|---|
| | 320 | int[] a = [1, 2, 3], b = [10, 20]; |
|---|
| | 321 | auto c = a; |
|---|
| | 322 | put(a, b); |
|---|
| | 323 | assert(c == [10, 20, 3]); |
|---|
| | 324 | assert(a == [3]); |
|---|
| | 325 | } |
|---|
| | 326 | |
|---|
| | 327 | unittest |
|---|
| | 328 | { |
|---|
| | 329 | int[] a = new int[10]; |
|---|
| | 330 | int b; |
|---|
| | 331 | static assert(isInputRange!(typeof(a))); |
|---|
| | 332 | put(a, b); |
|---|
| | 333 | } |
|---|
| | 334 | |
|---|
| | 335 | unittest |
|---|
| | 336 | { |
|---|
| | 337 | void myprint(in char[] s) { } |
|---|
| | 338 | auto r = &myprint; |
|---|
| | 339 | put(r, 'a'); |
|---|
| | 340 | } |
|---|
| | 341 | |
|---|
| | 342 | /** |
|---|
| | 343 | Returns $(D true) if $(D R) is an output range for elements of type |
|---|
| | 344 | $(D E). An output range can be defined functionally as a range that |
|---|
| | 345 | supports the operation $(D put(r, e)) as defined above. |
|---|
| | 346 | */ |
|---|
| | 347 | template isOutputRange(R, E) |
|---|
| | 348 | { |
|---|
| | 349 | enum bool isOutputRange = is(typeof({ R r; E e; put(r, e); }())); |
|---|
| 2374 | 2387 | { |
|---|
| 2375 | 2388 | auto fib = recurrence!("a[n-1] + a[n-2]")(1, 1); |
|---|
| 2376 | 2389 | int[] witness = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]; |
|---|
| 2377 | 2390 | //foreach (e; take(fib, 10)) writeln(e); |
|---|
| 2378 | 2391 | assert(equal(take(fib, 10), witness)); |
|---|
| 2379 | 2392 | foreach (e; take(fib, 10)) {}//writeln(e); |
|---|
| 2380 | 2393 | //writeln(s.front); |
|---|
| 2381 | 2394 | auto fact = recurrence!("n * a[n-1]")(1); |
|---|
| 2382 | 2395 | assert( equal(take(fact, 10), [1, 1, 2, 2*3, 2*3*4, 2*3*4*5, 2*3*4*5*6, |
|---|
| 2383 | 2396 | 2*3*4*5*6*7, 2*3*4*5*6*7*8, 2*3*4*5*6*7*8*9][]) ); |
|---|
| 2384 | 2397 | auto piapprox = recurrence!("a[n] + (n & 1 ? 4. : -4.) / (2 * n + 3)")(4.); |
|---|
| 2385 | 2398 | foreach (e; take(piapprox, 20)) {}//writeln(e); |
|---|