Changeset 1694
- Timestamp:
- 06/25/10 03:06:54 (14 years ago)
- Files:
-
- trunk/docsrc/changelog.dd (modified) (1 diff)
- trunk/phobos/std/range.d (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/docsrc/changelog.dd
r1692 r1694 13 13 $(LI $(BUGZILLA 978): std.utf's toUTF* functions accept some invalid and reject some valid UTF) 14 14 $(LI $(BUGZILLA 996): Error in doc on implicit conversion between pointer and array) 15 15 $(LI $(BUGZILLA 2275): std.utf.toUTF16z() should return const(wchar)*) 16 16 $(LI $(BUGZILLA 2872): Length, opIndex for Map) 17 17 $(LI $(BUGZILLA 3202): std.math.pow cause dead loop) 18 18 $(LI $(BUGZILLA 3355): std.string.cmp works incorrectly for mixed-type and different-length strings) 19 19 $(LI $(BUGZILLA 3386): to!bool(string) is not implemented) 20 20 $(LI $(BUGZILLA 3436): std.functional.compose with only one function) 21 21 $(LI $(BUGZILLA 3439): std.range.Sequence.opIndex not consistent after calling popFront().) 22 22 $(LI $(BUGZILLA 3447): std.file uses unconventional file permissions) 23 $(LI $(BUGZILLA 3874): std.range.stride assumes a bidirectional input range) 23 24 $(LI $(BUGZILLA 3937): os.path.dirname fails on absolute path) 24 25 $(LI $(BUGZILLA 3961): Error with to!(somestruct)) 25 26 $(LI $(BUGZILLA 4109): (reopened) writeln doesn't work with empty static array) 26 27 $(LI $(BUGZILLA 4171): std.random.uniform does not work for a range of characters) 27 28 $(LI $(BUGZILLA 4260): windows & basename) 29 $(LI $(BUGZILLA 4305): Take, Chain on top of ranges w/o moveFront() ) 28 30 $(LI $(BUGZILLA 4327): std.container.Array.Range.~this() tries to call free(T[])) 29 31 $(LI $(BUGZILLA 4362): std.range.repeat and cycle do not have a .save() method 30 32 $(LI $(BUGZILLA 4363): std.algorithm.Until is not a forward range) 31 33 ) 32 34 ) 33 35 34 36 <div id=version> 35 37 $(UL 36 38 $(NEW 048) 37 39 $(NEW 047) trunk/phobos/std/range.d
r1691 r1694 119 119 } 120 120 } 121 121 122 122 static if(l == Length.Yes) { 123 123 @property size_t length() { 124 124 return arr.length; 125 125 } 126 126 } 127 127 } 128 128 129 enum dummyLength = 10; 130 129 131 alias TypeTuple!( 130 132 DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Input), 131 133 DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Forward), 132 134 DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Bidirectional), 133 135 DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Random), 134 136 DummyRange!(ReturnBy.Reference, Length.No, RangeType.Input), 135 137 DummyRange!(ReturnBy.Reference, Length.No, RangeType.Forward), 136 138 DummyRange!(ReturnBy.Reference, Length.No, RangeType.Bidirectional), 137 DummyRange!(ReturnBy.Reference, Length.No, RangeType.Random),138 139 DummyRange!(ReturnBy.Value, Length.Yes, RangeType.Input), 139 140 DummyRange!(ReturnBy.Value, Length.Yes, RangeType.Forward), 140 141 DummyRange!(ReturnBy.Value, Length.Yes, RangeType.Bidirectional), 141 142 DummyRange!(ReturnBy.Value, Length.Yes, RangeType.Random), 142 143 DummyRange!(ReturnBy.Value, Length.No, RangeType.Input), 143 144 DummyRange!(ReturnBy.Value, Length.No, RangeType.Forward), 144 DummyRange!(ReturnBy.Value, Length.No, RangeType.Bidirectional), 145 DummyRange!(ReturnBy.Value, Length.No, RangeType.Random) 145 DummyRange!(ReturnBy.Value, Length.No, RangeType.Bidirectional) 146 146 ) AllDummyRanges; 147 147 148 148 alias TypeTuple!(1,2,3,4,5,6,7,8,9,0,11,12,13,14,15,16) DummyIndices; 149 149 } 150 150 151 151 /** 152 152 Returns $(D true) if $(D R) is an input range. An input range must 153 153 define the primitives $(D empty), $(D popFront), and $(D front). The 154 154 following code should compile for any input range. 155 155 … … 347 347 compilation) are assumed to be the following ($(D r) is an object of 348 348 type $(D R)): 349 349 $(UL $(LI $(D r.opIndex(n)) returns a reference to the $(D n)th 350 350 element in the range.)) 351 351 */ 352 352 template isRandomAccessRange(R) 353 353 { 354 354 enum bool isRandomAccessRange = 355 355 (isBidirectionalRange!(R) || isInfinite!(R)) 356 356 && is(typeof(R.init[1])) 357 && !isNarrowString!R; 357 && !isNarrowString!R 358 && (hasLength!R || isInfinite!R); 358 359 } 359 360 360 361 unittest 361 362 { 362 363 struct A {} 363 364 static assert(!isRandomAccessRange!(A)); 364 365 struct B 365 366 { 366 367 void popFront(); 367 368 bool empty(); … … 379 380 static assert(!isRandomAccessRange!(C)); 380 381 struct D 381 382 { 382 383 bool empty(); 383 384 @property D save(); 384 385 int front(); 385 386 void popFront(); 386 387 int back(); 387 388 void popBack(); 388 389 ref int opIndex(uint); 390 @property size_t length(); 389 391 //int opSlice(uint, uint); 390 392 } 391 393 static assert(isRandomAccessRange!(D)); 392 394 static assert(isRandomAccessRange!(int[])); 393 395 } 394 396 395 397 /** 396 398 The element type of $(D R). $(D R) does not have to be a range. The 397 399 element type is determined as the type yielded by $(D r.front) for an 398 400 object $(D r) or type $(D R). For example, $(D ElementType!(T[])) is … … 931 933 } 932 934 test(1, [], []); 933 935 int[] arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; 934 936 test(1, arr, arr); 935 937 test(2, arr, [1, 3, 5, 7, 9]); 936 938 test(3, arr, [1, 4, 7, 10]); 937 939 test(4, arr, [1, 5, 9]); 938 940 939 941 foreach(DummyType; AllDummyRanges) { 940 942 static if(DummyType.r == ReturnBy.Reference) { 941 // Doesn't work yet w/o ref returns, see DMD bug 3294 .943 // Doesn't work yet w/o ref returns, see DMD bug 3294 and 3894. 942 944 DummyType dummyRange; 943 945 dummyRange.reinit(); 944 946 945 947 auto myStride = stride(dummyRange, 4); 946 948 assert(myStride.front == 1); 947 949 assert(equal(myStride, [1, 5, 9])); 948 950 949 951 static if(hasLength!DummyType) { 950 952 assert(myStride.length == 3); 951 953 } … … 1236 1238 uint[] foo = [1,2,3,4,5]; 1237 1239 uint[] bar = [1,2,3,4,5]; 1238 1240 auto c = chain(foo, bar); 1239 1241 c[3] = 42; 1240 1242 assert(c[3] == 42); 1241 1243 } 1242 1244 1243 1245 // Make sure bug 3311 is fixed. ChainImpl should compile even if not all 1244 1246 // elements are mutable. 1245 1247 auto c = chain( iota(0, 10), iota(0, 10) ); 1248 1249 // Check that chain at least instantiates and compiles with every possible 1250 // pair of DummyRange types, in either order. 1251 1252 // This test should be uncommented when DMD bug 4379 gets fixed. 1253 // foreach(DummyType1; AllDummyRanges) { 1254 // DummyType1 dummy1; 1255 // foreach(DummyType2; AllDummyRanges) { 1256 // DummyType2 dummy2; 1257 // auto myChain = chain(dummy1, dummy2); 1258 // assert(myChain.front == 1); 1259 // foreach(i; 0..dummyLength) { 1260 // myChain.popFront(); 1261 // } 1262 // assert(myChain.front == 1); 1263 // } 1264 // } 1265 1246 1266 } 1247 1267 1248 1268 /** 1249 1269 Iterates a random-access range starting from a given point and 1250 1270 progressively extending left and right from that point. If no initial 1251 1271 point is given, iteration starts from the middle of the 1252 1272 range. Iteration spans the entire range. 1253 1273 1254 1274 Example: 1255 1275 ---- … … 1386 1406 } 1387 1407 test([], []); 1388 1408 test([ 1 ], [ 1 ]); 1389 1409 test([ 1, 2 ], [ 1, 2 ]); 1390 1410 test([ 1, 2, 3 ], [ 2, 3, 1 ]); 1391 1411 test([ 1, 2, 3, 4 ], [ 2, 3, 1, 4 ]); 1392 1412 test([ 1, 2, 3, 4, 5 ], [ 3, 4, 2, 5, 1 ]); 1393 1413 test([ 1, 2, 3, 4, 5, 6 ], [ 3, 4, 2, 5, 1, 6 ]); 1394 1414 int[] a = [ 1, 2, 3, 4, 5 ]; 1395 1415 assert(equal(radial(a, 1), [ 2, 3, 1, 4, 5 ][])); 1416 1417 // Test instantiation without lvalue elements. 1418 1419 // Doesn't instantiate! 1420 //DummyRange!(ReturnBy.Value, Length.Yes, RangeType.Random) dummy; 1421 //assert(equal(radial(dummy, 4), [5, 6, 4, 7, 3, 8, 2, 9, 1])); 1396 1422 } 1397 1423 1398 1424 /** 1399 1425 Lazily takes only up to $(D n) elements of a range. This is 1400 1426 particulary useful when using with infinite ranges. If the range 1401 1427 offers random access and $(D length), $(D Take) offers them as well. 1402 1428 1403 1429 Example: 1404 1430 ---- 1405 1431 int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; … … 1540 1566 } 1541 1567 1542 1568 unittest 1543 1569 { 1544 1570 int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; 1545 1571 auto s = take(arr1, 5); 1546 1572 assert(s.length == 5); 1547 1573 assert(s[4] == 5); 1548 1574 assert(equal(s, [ 1, 2, 3, 4, 5 ][])); 1549 1575 assert(equal(retro(s), [ 5, 4, 3, 2, 1 ][])); 1576 1577 foreach(DummyType; AllDummyRanges) { 1578 DummyType dummy; 1579 auto t = take(dummy, 5); 1580 assert(equal(t, [1,2,3,4,5])); 1581 } 1550 1582 } 1551 1583 1552 1584 /** 1553 1585 Eagerly advances $(D r) itself (not a copy) $(D n) times (by calling 1554 1586 $(D r.popFront) $(D n) times). The pass of $(D r) into $(D popFrontN) 1555 1587 is by reference, so the original range is affected. Completes in 1556 1588 $(BIGOH 1) steps for ranges that support slicing, and in $(BIGOH n) 1557 1589 time for all other ranges. 1558 1590 1559 1591 Example: … … 1716 1748 /// Ditto 1717 1749 @property Cycle!(R) save() { 1718 1750 return Cycle!(R)(this._original.save, this._index); 1719 1751 } 1720 1752 } 1721 1753 else 1722 1754 { 1723 1755 R _original, _current; 1724 1756 this(R input) { _original = input; _current = input.save; } 1725 1757 /// Range primitive implementations. 1726 auto reffront() { return _current.front; }1758 ref ElementType!(R) front() { return _current.front; } 1727 1759 /// Ditto 1728 1760 static if (isBidirectionalRange!(R)) 1729 1761 ref ElementType!(R) back() { return _current.back; } 1730 1762 /// Ditto 1731 1763 enum bool empty = false; 1732 1764 /// Ditto 1733 1765 void popFront() 1734 1766 { 1735 1767 _current.popFront; 1736 1768 if (_current.empty) _current = _original; … … 1811 1843 { 1812 1844 assert(equal(take(cycle([1, 2][]), 5), [ 1, 2, 1, 2, 1 ][])); 1813 1845 static assert(isForwardRange!(Cycle!(uint[]))); 1814 1846 1815 1847 int[3] a = [ 1, 2, 3 ]; 1816 1848 static assert(isStaticArray!(typeof(a))); 1817 1849 auto c = cycle(a); 1818 1850 assert(a.ptr == c._ptr); 1819 1851 assert(equal(take(cycle(a), 5), [ 1, 2, 3, 1, 2 ][])); 1820 1852 static assert(isForwardRange!(typeof(c))); 1853 1854 foreach(DummyType; AllDummyRanges) { 1855 // Bug 4387 1856 static if(isForwardRange!(DummyType) && DummyType.r == ReturnBy.Reference) { 1857 DummyType dummy; 1858 auto cy = cycle(dummy); 1859 static assert(isForwardRange!(typeof(cy))); 1860 auto t = take(cy, 20); 1861 assert(equal(t, [1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10])); 1862 } 1863 } 1821 1864 } 1822 1865 1823 1866 unittest // For infinite ranges 1824 1867 { 1825 1868 struct InfRange 1826 1869 { 1827 1870 void popFront() { } 1828 1871 int front() { return 0; } 1829 1872 enum empty = false; 1830 1873 } … … 2839 2882 auto tr = transposed(x); 2840 2883 int[][] witness = [ [ 1, 3 ], [ 2, 4 ] ]; 2841 2884 uint i; 2842 2885 2843 2886 foreach (e; tr) 2844 2887 { 2845 2888 assert(array(e) == witness[i++]); 2846 2889 } 2847 2890 } 2848 2891 2892 // Tests to see whether a struct has a postblit. Hacky, probably needs to 2893 // be fixed if a new frontend is ever written. 2894 private template hasPostblit(R) { 2895 static if(!is(R == struct)) { 2896 enum bool hasPostblit = false; 2897 } else { 2898 enum hasPostblit = is(typeof({ 2899 R r; 2900 return &r.__postblit; 2901 })); 2902 } 2903 } 2904 2905 unittest { 2906 struct S { 2907 this(this) {} 2908 } 2909 2910 struct S2 {} 2911 2912 static assert(hasPostblit!S); 2913 static assert(!hasPostblit!S2); 2914 } 2915 2849 2916 /** 2850 2917 Moves the front of $(D r) out and returns it. Leaves $(D r.front) in a 2851 2918 destroyable state that does not allocate any resources (usually equal 2852 2919 to its $(D .init) value). 2853 2920 */ 2854 2921 ElementType!R moveFront(R)(R r) 2855 if (is(typeof(&r.front()) == ElementType!R*)) 2856 { 2857 return move(r.front); 2922 { 2923 static if(is(typeof(&R.moveFront))) { 2924 return r.moveFront(); 2925 } else static if(!hasPostblit!(ElementType!(R))) { 2926 return r.front; 2927 } else static if(is(typeof(&r.front()) == ElementType!R*)) { 2928 return move(r.front); 2929 } else { 2930 static assert(0, 2931 "Cannot move front of a range with a postblit and an rvalue front."); 2932 } 2858 2933 } 2859 2934 2860 2935 unittest 2861 2936 { 2862 2937 struct R 2863 2938 { 2864 2939 ref int front() { static int x = 42; return x; } 2940 this(this){} 2865 2941 } 2866 2942 R r; 2867 2943 assert(moveFront(r) == 42); 2868 }2869 2870 /// Ditto2871 ElementType!R moveFront(R)(R r)2872 if (is(typeof(&R.moveFront)))2873 {2874 return r.moveFront();2875 2944 } 2876 2945 2877 2946 /** 2878 2947 Moves the front of $(D r) out and returns it. Leaves $(D r.front) in a 2879 2948 destroyable state that does not allocate any resources (usually equal 2880 2949 to its $(D .init) value). 2881 2950 */ 2882 2951 ElementType!R moveBack(R)(R r) 2883 2952 if (isInputRange!R && is(typeof(&r.front) == ElementType!R*)) 2884 2953 {
