digitalmars.D.learn - .sort vs sort(): std.algorithm not up to the task?
- Andrew Edwards (23/23) Jun 07 2017 Ranges may be finite or infinite but, while the destination may
- Mike B Johnson (5/8) Jun 07 2017 Because is like a poodle and unless you get your hair cut in a
- Andrew Edwards (4/13) Jun 07 2017 Pretty funny. But seriously, this is something that just work.
- Andrew Edwards (2/5) Jun 07 2017 *should just work
- Era Scarecrow (8/11) Jun 07 2017 Hmmm while working on my recent sudoku solver using pointers to
- Stanislav Blinov (4/27) Jun 07 2017 aa.keys.sort() should just work as is: aa.keys returns a
- Andrew Edwards (3/6) Jun 07 2017 It does not ... I provided the code and related error message.
- Jonathan M Davis via Digitalmars-d-learn (29/49) Jun 07 2017 Ranges do not support iterating with an index. The workaround if you wan...
- Stanislav Blinov (9/19) Jun 07 2017 There's an enumerate():
- Jonathan M Davis via Digitalmars-d-learn (4/28) Jun 07 2017 Even better. I hadn't realized that such a function had been added.
- Andrew Edwards (14/39) Jun 07 2017 Note that I already demonstrated the same functionality by
- Jonathan M Davis via Digitalmars-d-learn (8/54) Jun 07 2017 sort() returns a SortedRange so that other algorithms can know that the
- Andrew Edwards (12/29) Jun 07 2017 Yes, I understand that. Again, using "std.range: release" earns
- Stanislav Blinov (11/25) Jun 07 2017 Earns you nothing? How about not performing an allocation and
- Andrew Edwards (16/31) Jun 07 2017 Seen through the eyes of a complete beginner, this means
- Jonathan M Davis via Digitalmars-d-learn (35/66) Jun 08 2017 release is a member of SortedRange. You don't have to import it separate...
- Andrew Edwards (6/13) Jun 08 2017 sorry, I missed that after accidentally making the change in on
- Russel Winder via Digitalmars-d-learn (17/26) Jun 08 2017 [=E2=80=A6]
- Russel Winder via Digitalmars-d-learn (14/17) Jun 08 2017 [=E2=80=A6]
- Seb (8/15) Jun 07 2017 A magician should never reveal his secrets, but this I do share.
- 9il (5/28) Jun 08 2017 You may want to slice chihuahua first, pass it to
- Timon Gehr (5/34) Jun 08 2017 You are not giving away the chihuahua.
- Steven Schveighoffer (16/38) Jun 08 2017 The issue here is that arrays are special. Arrays allow foreach(i, v;
- Timon Gehr (5/16) Jun 08 2017 Arguably, foreach over ranges and foreach over arrays are badly
Ranges may be finite or infinite but, while the destination may be unreachable, we can definitely tell how far we've traveled. So why doesn't this work? import std.traits; import std.range; void main() { string[string] aa; // what others have referred to as // standard sort works but is deprecated //auto keys = aa.keys.sort; // Error: cannot infer argument types, expected 1 argument, not 2 import std.algorithm: sort; auto keys = aa.keys.sort(); // this works but why should I have to? //import std.array: array; //auto keys = aa.keys.sort().array; foreach (i, v; keys){} } If I hand you a chihuahua for grooming, why am I getting back a pit bull? I simply want a groomed chihuahua. Why do I need to consult a wizard to get back a groomed chihuahua?
Jun 07 2017
On Thursday, 8 June 2017 at 01:57:47 UTC, Andrew Edwards wrote:If I hand you a chihuahua for grooming, why am I getting back a pit bull? I simply want a groomed chihuahua. Why do I need to consult a wizard to get back a groomed chihuahua?Because is like a poodle and unless you get your hair cut in a special way you won't be considered for the job! The wizard only exists to balance the symmetric arrangement of the interplanetary forces, don't fear him, he does his job in a very predictable way.
Jun 07 2017
On Thursday, 8 June 2017 at 02:07:07 UTC, Mike B Johnson wrote:On Thursday, 8 June 2017 at 01:57:47 UTC, Andrew Edwards wrote:Pretty funny. But seriously, this is something that just work. There is now to layers of indirection to achieve what I used to do quite naturally in the language.If I hand you a chihuahua for grooming, why am I getting back a pit bull? I simply want a groomed chihuahua. Why do I need to consult a wizard to get back a groomed chihuahua?Because is like a poodle and unless you get your hair cut in a special way you won't be considered for the job! The wizard only exists to balance the symmetric arrangement of the interplanetary forces, don't fear him, he does his job in a very predictable way.
Jun 07 2017
On Thursday, 8 June 2017 at 02:19:15 UTC, Andrew Edwards wrote:Pretty funny. But seriously, this is something that just work. There is now to layers of indirection to achieve what I used to do quite naturally in the language.*should just work
Jun 07 2017
On Thursday, 8 June 2017 at 02:19:15 UTC, Andrew Edwards wrote:Pretty funny. But seriously, this is something that should just work. There is now to layers of indirection to achieve what I used to do quite naturally in the language.Hmmm while working on my recent sudoku solver using pointers to structs, i had opCmp defined, but it was still sorting by pointer address rather than how i told it to sort; I had to give it the hint of sort!"*a < *b" for it to work right. It does seem like a little more duct-tape on the wizard is needed in some cases. Thankfully it isn't too complex to know where to tape the wand into the wizard's hand.
Jun 07 2017
On Thursday, 8 June 2017 at 01:57:47 UTC, Andrew Edwards wrote:Ranges may be finite or infinite but, while the destination may be unreachable, we can definitely tell how far we've traveled. So why doesn't this work? import std.traits; import std.range; void main() { string[string] aa; // what others have referred to as // standard sort works but is deprecated //auto keys = aa.keys.sort; // Error: cannot infer argument types, expected 1 argument, not 2 import std.algorithm: sort; auto keys = aa.keys.sort(); // this works but why should I have to? //import std.array: array; //auto keys = aa.keys.sort().array; foreach (i, v; keys){} } If I hand you a chihuahua for grooming, why am I getting back a pit bull? I simply want a groomed chihuahua. Why do I need to consult a wizard to get back a groomed chihuahua?aa.keys.sort() should just work as is: aa.keys returns a string[], and that's a random access range that can be sorted. What exactly is the error?
Jun 07 2017
On Thursday, 8 June 2017 at 02:21:03 UTC, Stanislav Blinov wrote:aa.keys.sort() should just work as is: aa.keys returns a string[], and that's a random access range that can be sorted. What exactly is the error?It does not ... I provided the code and related error message. See the line right above "import std.algorith: sort;".
Jun 07 2017
On Thursday, June 08, 2017 01:57:47 Andrew Edwards via Digitalmars-d-learn wrote:Ranges may be finite or infinite but, while the destination may be unreachable, we can definitely tell how far we've traveled. So why doesn't this work? import std.traits; import std.range; void main() { string[string] aa; // what others have referred to as // standard sort works but is deprecated //auto keys = aa.keys.sort; // Error: cannot infer argument types, expected 1 argument, not 2 import std.algorithm: sort; auto keys = aa.keys.sort(); // this works but why should I have to? //import std.array: array; //auto keys = aa.keys.sort().array; foreach (i, v; keys){} }Ranges do not support iterating with an index. The workaround if you want to have an index with ranges and foreach, then you should use lockstep: http://dlang.org/phobos/std_range.html#lockstep e.g. foreach(i, v; lockstep(iota!size_t(0), s)) {} or foreach(i, v; lockstep(iota(0), s)) {} if you don't mind i being an int instead of a size_t. Now, with your example, there are two other solutions that are even easier. sort() sorts the range that it's given in place but returns a wrapper range so that other algorithms can recognize the range as sorted. So, if you did auto keys = aa.keys; sort(keys); foreach(i; v) {} then it will work just fine, because you're still dealing with an array. Alternatively, you could use SortedRange's release function to get the array out of the SortedRange (though note if you do that, you shouldn't then use the SortedRange anymore, since it does a move call to actual move the wrapped range out of the SortedRange). e.g. auto keys = aa.keys.sort().release(); foreach(i; v) {} and that would allow you to still do it in one line. - Jonathan M Davis
Jun 07 2017
On Thursday, 8 June 2017 at 02:25:17 UTC, Jonathan M Davis wrote: Oh I see, the was error related to iteration, not sorting.Ranges do not support iterating with an index. The workaround if you want to have an index with ranges and foreach, then you should use lockstep: http://dlang.org/phobos/std_range.html#lockstep e.g. foreach(i, v; lockstep(iota!size_t(0), s)) {} or foreach(i, v; lockstep(iota(0), s)) {}There's an enumerate(): https://dlang.org/phobos/std_range.html#enumerate import std.algorithm : sort; import std.range : enumerate; foreach(i, k; aa.keys.sort().enumerate) { /* ... */ }
Jun 07 2017
On Thursday, June 08, 2017 02:31:43 Stanislav Blinov via Digitalmars-d-learn wrote:On Thursday, 8 June 2017 at 02:25:17 UTC, Jonathan M Davis wrote: Oh I see, the was error related to iteration, not sorting.Even better. I hadn't realized that such a function had been added. - Jonathan M DavisRanges do not support iterating with an index. The workaround if you want to have an index with ranges and foreach, then you should use lockstep: http://dlang.org/phobos/std_range.html#lockstep e.g. foreach(i, v; lockstep(iota!size_t(0), s)) {} or foreach(i, v; lockstep(iota(0), s)) {}There's an enumerate(): https://dlang.org/phobos/std_range.html#enumerate import std.algorithm : sort; import std.range : enumerate; foreach(i, k; aa.keys.sort().enumerate) { /* ... */ }
Jun 07 2017
On Thursday, 8 June 2017 at 02:31:43 UTC, Stanislav Blinov wrote:On Thursday, 8 June 2017 at 02:25:17 UTC, Jonathan M Davis wrote: Oh I see, the was error related to iteration, not sorting.Note that I already demonstrated the same functionality by importing "std.array: array" to get the job done. Neither lockstep nor enumerate gets me more benefit in this particular situation that array doesn't already get me. My question here is not whether the job can get done or not, it's simply why the extra work? I still have to import two modules, when before I didn't have to import any. I completely understand the differences between ranges and arrays... the thing is, I wasn't working with ranges but arrays instead. If sort understands a string or array as a sort of range, then given one of those entities, it should manipulate it internally and return it in it's original flavor. Given an array, return an array unless specifically told to do otherwise.Ranges do not support iterating with an index. The workaround if you want to have an index with ranges and foreach, then you should use lockstep: http://dlang.org/phobos/std_range.html#lockstep e.g. foreach(i, v; lockstep(iota!size_t(0), s)) {} or foreach(i, v; lockstep(iota(0), s)) {}There's an enumerate(): https://dlang.org/phobos/std_range.html#enumerate import std.algorithm : sort; import std.range : enumerate; foreach(i, k; aa.keys.sort().enumerate) { /* ... */ }
Jun 07 2017
On Thursday, June 08, 2017 03:15:11 Andrew Edwards via Digitalmars-d-learn wrote:On Thursday, 8 June 2017 at 02:31:43 UTC, Stanislav Blinov wrote:sort() returns a SortedRange so that other algorithms can know that the range is sorted and take advantage of that. If sort() returned the original range type, it would be detrimental for other algorithms. But you can just use the array directly again after calling sort or call release() on the SortedRange to get the array out of it. - Jonathan M DavisOn Thursday, 8 June 2017 at 02:25:17 UTC, Jonathan M Davis wrote: Oh I see, the was error related to iteration, not sorting.Note that I already demonstrated the same functionality by importing "std.array: array" to get the job done. Neither lockstep nor enumerate gets me more benefit in this particular situation that array doesn't already get me. My question here is not whether the job can get done or not, it's simply why the extra work? I still have to import two modules, when before I didn't have to import any. I completely understand the differences between ranges and arrays... the thing is, I wasn't working with ranges but arrays instead. If sort understands a string or array as a sort of range, then given one of those entities, it should manipulate it internally and return it in it's original flavor. Given an array, return an array unless specifically told to do otherwise.Ranges do not support iterating with an index. The workaround if you want to have an index with ranges and foreach, then you should use lockstep: http://dlang.org/phobos/std_range.html#lockstep e.g. foreach(i, v; lockstep(iota!size_t(0), s)) {} or foreach(i, v; lockstep(iota(0), s)) {}There's an enumerate(): https://dlang.org/phobos/std_range.html#enumerate import std.algorithm : sort; import std.range : enumerate; foreach(i, k; aa.keys.sort().enumerate) { /* ... */ }
Jun 07 2017
On Thursday, 8 June 2017 at 03:40:08 UTC, Jonathan M Davis wrote:On Thursday, June 08, 2017 03:15:11 Andrew Edwards via Digitalmars-d-learn wrote:Yes, I understand that. Again, using "std.range: release" earns me nothing more than I already get from "std.array: array" or if you prefer "std.range: array". I can understand if sort returns Range by default but can be instructed to return the original representation. aa.keys.sort!returnOriginalRepresentation; // or something to that effect But it doesn't, it decides what i'm gonna get like it or not. But the fact, a lot of times I just want to work with the underlying data after the operation is performed. And it should be noted that this applies to Ranges in general not just sort.I completely understand the differences between ranges and arrays... the thing is, I wasn't working with ranges but arrays instead. If sort understands a string or array as a sort of range, then given one of those entities, it should manipulate it internally and return it in it's original flavor. Given an array, return an array unless specifically told to do otherwise.sort() returns a SortedRange so that other algorithms can know that the range is sorted and take advantage of that. If sort() returned the original range type, it would be detrimental for other algorithms. But you can just use the array directly again after calling sort or call release() on the SortedRange to get the array out of it. - Jonathan M Davis
Jun 07 2017
On Thursday, 8 June 2017 at 04:07:22 UTC, Andrew Edwards wrote:On Thursday, 8 June 2017 at 03:40:08 UTC, Jonathan M DavisEarns you nothing? How about not performing an allocation and copy?sort() returns a SortedRange so that other algorithms can know...Yes, I understand that. Again, using "std.range: release" earns me nothing more than I already get from "std.array: array" or if you prefer "std.range: array".I can understand if sort returns Range by default but can be instructed to return the original representation.aa.keys.sort!returnOriginalRepresentation; // or something to that effect"Something to that effect" is exactly this: aa.keys.sort().release; No need to import anything but std.algorithm : sort.But it doesn't, it decides what i'm gonna get like it or not. But the fact, a lot of times I just want to work with the underlying data after the operation is performed. And it should be noted that this applies to Ranges in general not just sort.A crucial point of any good design is to *not rob the caller of useful information*. sort() follows that philosophy. If you don't need the extra information, you're free to get rid of it. The other way around that you seem to be proposing would require having a ton of overloads for sort() for any imaginable use case.
Jun 07 2017
On Thursday, 8 June 2017 at 04:15:12 UTC, Stanislav Blinov wrote:Earns you nothing? How about not performing an allocation and copy?Seen through the eyes of a complete beginner, this means absolutely nothing. Those are the eyes I am using as I'm reading a book and simply following the instructions provided. I took care of the problem with the first thing that came to mind, because that all that's required.aa.keys.sort().release;somehow, I missed the point that actually came as a byproduct of importing sort. When I tried it in the original code it "ostensibly" did not work because, i recompiled the edited version posed here.No need to import anything but std.algorithm : sort.No I'm not proposing that at all, if the predicate is initialized such that it functions the exact same way it does now, then only in instances where necessary would the user need to specify anything. Anyway, the functionality I'm asking for is the one forded by release so i'm satisfied. Thank you.But it doesn't, it decides what i'm gonna get like it or not. But the fact, a lot of times I just want to work with the underlying data after the operation is performed. And it should be noted that this applies to Ranges in general not just sort.A crucial point of any good design is to *not rob the caller of useful information*. sort() follows that philosophy. If you don't need the extra information, you're free to get rid of it. The other way around that you seem to be proposing would require having a ton of overloads for sort() for any imaginable use case.
Jun 07 2017
On Thursday, June 08, 2017 04:07:22 Andrew Edwards via Digitalmars-d-learn wrote:On Thursday, 8 June 2017 at 03:40:08 UTC, Jonathan M Davis wrote:release is a member of SortedRange. You don't have to import it separately. You have it automatically by virtue of the fact that sort returns a SortedRange. And unlike calling array, it doesn't copy the entire range or allocate.On Thursday, June 08, 2017 03:15:11 Andrew Edwards via Digitalmars-d-learn wrote:Yes, I understand that. Again, using "std.range: release" earns me nothing more than I already get from "std.array: array" or if you prefer "std.range: array". I can understand if sort returns Range by default but can be instructed to return the original representation.I completely understand the differences between ranges and arrays... the thing is, I wasn't working with ranges but arrays instead. If sort understands a string or array as a sort of range, then given one of those entities, it should manipulate it internally and return it in it's original flavor. Given an array, return an array unless specifically told to do otherwise.sort() returns a SortedRange so that other algorithms can know that the range is sorted and take advantage of that. If sort() returned the original range type, it would be detrimental for other algorithms. But you can just use the array directly again after calling sort or call release() on the SortedRange to get the array out of it. - Jonathan M Davisaa.keys.sort!returnOriginalRepresentation; // or something to that effect But it doesn't, it decides what i'm gonna get like it or not. But the fact, a lot of times I just want to work with the underlying data after the operation is performed. And it should be noted that this applies to Ranges in general not just sort.It's just life with ranges that you're usually going to end up with a new type when you call a range-based functions. Most of them can't even do what they're supposed to do without returning a new type, and that type often is not same level of range as the original (e.g. filter returns a new range, and it's only a forward range even if the original is a random-access range, and it can't do otherwise given that it's lazy). Pretty much the only way for ranges in general to return the same type would be if you were only dealing with dynamic arrays, and you were willing to have the range-based function not only be non-lazy, but you were also willing to have it allocate. And if you're going that route, you might as well just have functions operating on dynamic arrays instead of ranges. As it stands, we have functions that return lazy ranges so that they're efficient, and if you want a dynamic array back, you call array on the result. Sure, if you're looking to only operate on dynamic arrays, then that can be a bit annoying, but overall, it leads to much more efficient code, and a lot of code works just fine without to call array having to worry about whether dynamic arrays are involved at all. It's true that sort could work with returning the original type and without allocating (unlike a function like filter), but having it return SortedRange is beneficial overall, and calling release to get the original out is as short as passing a template argument like you're suggesting. Also, you can simply call sort on a separate line and continue to use the array without worrying about sort's return value. So, while I can understand that you'd like sort to just return the array in this case, it's so simple to work around it that this really doesn't seem like it should be a big deal. The reality of the matter is that if you're going to be annoyed about range-based functions returning new types, you're going to be annoyed a lot when dealing with range-based functions. - Jonathan M Davis
Jun 08 2017
On Thursday, 8 June 2017 at 07:23:27 UTC, Jonathan M Davis wrote:release is a member of SortedRange. You don't have to import it separately. You have it automatically by virtue of the fact that sort returns a SortedRange. And unlike calling array, it doesn't copy the entire range or allocate.sorry, I missed that after accidentally making the change in on file and compiled another.having it return SortedRange is beneficial overall, and calling release to get the original out is as short as passing a template argument like you're suggesting.a point I missed do to the aforementioned mistake. Thanks for the assist, Andrew
Jun 08 2017
On Thu, 2017-06-08 at 00:23 -0700, Jonathan M Davis via Digitalmars-d- learn wrote:[=E2=80=A6] =20 release is a member of SortedRange. You don't have to import it separately. You have it automatically by virtue of the fact that sort returns a SortedRange. And unlike calling array, it doesn't copy the entire range or allocate. =20[=E2=80=A6] I will have to admit, that on my recent return to more full time D programming, that using both class members, and imported functions with UFCS, can lead to annoyance of understanding. I can't put my finger on what paragraph of documentation would help just yet though. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Jun 08 2017
On Wed, 2017-06-07 at 19:39 -0700, Jonathan M Davis via Digitalmars-d- learn wrote:=20[=E2=80=A6]Even better. I hadn't realized that such a function had been added. =20Another import from Python. :-) --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Jun 08 2017
On Thursday, 8 June 2017 at 01:57:47 UTC, Andrew Edwards wrote:Ranges may be finite or infinite but, while the destination may be unreachable, we can definitely tell how far we've traveled. So why doesn't this work? ... If I hand you a chihuahua for grooming, why am I getting back a pit bull? I simply want a groomed chihuahua. Why do I need to consult a wizard to get back a groomed chihuahua?A magician should never reveal his secrets, but this I do share. .sort() returns a SortedRange [1] that encapsulates the range. The trick is to use .release() to release the controlled range and return it, e.g. import std.algorithm : sort; auto keys = aa.keys.sort().release; [1] https://dlang.org/phobos/std_range.html#SortedRange
Jun 07 2017
On Thursday, 8 June 2017 at 01:57:47 UTC, Andrew Edwards wrote:Ranges may be finite or infinite but, while the destination may be unreachable, we can definitely tell how far we've traveled. So why doesn't this work? import std.traits; import std.range; void main() { string[string] aa; // what others have referred to as // standard sort works but is deprecated //auto keys = aa.keys.sort; // Error: cannot infer argument types, expected 1 argument, not 2 import std.algorithm: sort; auto keys = aa.keys.sort(); // this works but why should I have to? //import std.array: array; //auto keys = aa.keys.sort().array; foreach (i, v; keys){} } If I hand you a chihuahua for grooming, why am I getting back a pit bull? I simply want a groomed chihuahua. Why do I need to consult a wizard to get back a groomed chihuahua?You may want to slice chihuahua first, pass it to mir.ndslice.sort [1], and get back your groomed sliced chihuahua. [1]
Jun 08 2017
On 08.06.2017 03:57, Andrew Edwards wrote:Ranges may be finite or infinite but, while the destination may be unreachable, we can definitely tell how far we've traveled. So why doesn't this work? import std.traits; import std.range; void main() { string[string] aa; // what others have referred to as // standard sort works but is deprecated //auto keys = aa.keys.sort; // Error: cannot infer argument types, expected 1 argument, not 2 import std.algorithm: sort; auto keys = aa.keys.sort(); // this works but why should I have to? //import std.array: array; //auto keys = aa.keys.sort().array; foreach (i, v; keys){} } If I hand you a chihuahua for grooming, why am I getting back a pit bull? I simply want a groomed chihuahua. Why do I need to consult a wizard to get back a groomed chihuahua?You are not giving away the chihuahua. auto keys = aa.keys; sort(keys); foreach(i,v;keys){}
Jun 08 2017
On 6/7/17 9:57 PM, Andrew Edwards wrote:Ranges may be finite or infinite but, while the destination may be unreachable, we can definitely tell how far we've traveled. So why doesn't this work? import std.traits; import std.range; void main() { string[string] aa; // what others have referred to as // standard sort works but is deprecated //auto keys = aa.keys.sort; // Error: cannot infer argument types, expected 1 argument, not 2 import std.algorithm: sort; auto keys = aa.keys.sort(); // this works but why should I have to? //import std.array: array; //auto keys = aa.keys.sort().array; foreach (i, v; keys){} } If I hand you a chihuahua for grooming, why am I getting back a pit bull? I simply want a groomed chihuahua. Why do I need to consult a wizard to get back a groomed chihuahua?The issue here is that arrays are special. Arrays allow foreach(i, v; arr) and foreach(v; arr). Ranges in general do not. So there is no way to forward this capability via the range interface. Not only that, but foreach(i, v; arr) is much different than iterating even a range that returns a tuple in that the index is *specific to the loop* and doesn't involve the array at all. It's more similar to opApply. opApply can help, but still is different than how arrays work (foreach with array is handled directly by the compiler). But ranges are not going to be forwarding this feature just for arrays. In answer to your question, if we returned something that *didn't* take advantage of the fact that the range is now sorted, then people who want that functionality (e.g. builtin binary search) would be complaining. As a recommendation, I suggest you get used to using enumerate, as it will work for all cases of ranges, including arrays. -Steve
Jun 08 2017
On 08.06.2017 14:06, Steven Schveighoffer wrote:The issue here is that arrays are special. Arrays allow foreach(i, v; arr) and foreach(v; arr). Ranges in general do not. So there is no way to forward this capability via the range interface. Not only that, but foreach(i, v; arr) is much different than iterating even a range that returns a tuple in that the index is *specific to the loop* and doesn't involve the array at all. It's more similar to opApply. opApply can help, but still is different than how arrays work (foreach with array is handled directly by the compiler). But ranges are not going to be forwarding this feature just for arrays.Arguably, foreach over ranges and foreach over arrays are badly designed. Automatic tuple expansion only works with ranges, and indexed iteration only works with arrays, and they are mutually incompatible. Therefore, there is no good way to fix the problem.
Jun 08 2017