foreach for ranges?
How exactly does the compiler know how to do foreach on ranges (for example, ones returned by std.algorithm.map ?) I've looked around in std.algorithm and std.range, but can't seem to figure it out.
Re: foreach for ranges?
On 07/17/2012 11:59 AM, Mike L. wrote: How exactly does the compiler know how to do foreach on ranges (for example, ones returned by std.algorithm.map ?) I've looked around in std.algorithm and std.range, but can't seem to figure it out. The spec mentions it under 'Foreach over Structs and Classes with Ranges': http://dlang.org/statement.html#ForeachStatement There are two methods: a) opApply() member functions (and opApplyReverse(), which is rumored to be deprecated in the future) b) empty, front, and popFront() member functions Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
Re: foreach for ranges?
On Tuesday, July 17, 2012 20:59:12 Mike L. wrote: > How exactly does the compiler know how to do foreach on ranges > (for example, ones returned by std.algorithm.map ?) I've looked > around in std.algorithm and std.range, but can't seem to figure > it out. It translates foreach(e; range) {} into something like foreach(auto __range = range; !__range.empty; __range.popFront()) { auto e = __range.front; } The compiler knows just enough about ranges to enable foreach, but beyond that, ranges are entirely a library construct. - Jonathan M Davis
Re: foreach for ranges?
On Tuesday, 17 July 2012 at 19:27:54 UTC, Jonathan M Davis wrote: It translates foreach(e; range) {} into something like foreach(auto __range = range; !__range.empty; __range.popFront()) { auto e = __range.front; } The compiler knows just enough about ranges to enable foreach, but beyond that, ranges are entirely a library construct. The spec' says "If the foreach range properties do not exist, the opApply method will be used instead.", does this mean that range properties take precedence over opApply ?
Re: foreach for ranges?
On Tuesday, July 17, 2012 21:38:51 Eyyub wrote: > On Tuesday, 17 July 2012 at 19:27:54 UTC, Jonathan M Davis wrote: > > It translates > > > > foreach(e; range) > > {} > > > > into something like > > > > foreach(auto __range = range; !__range.empty; > > __range.popFront()) > > { > > > > auto e = __range.front; > > > > } > > > > The compiler knows just enough about ranges to enable foreach, > > but beyond > > that, ranges are entirely a library construct. > > The spec' says "If the foreach range properties do not exist, the > opApply method will be used instead.", does this mean that range > properties take precedence over opApply ? This post gives the current precedence, but there was some discussion of adjusting it a bit: http://forum.dlang.org/post/mailman.275.1342019430.31962.digitalmars- d...@puremagic.com >From the looks of it, opApply gets precedence right now. But mixing ranges and opApply isn't a good idea in most cases, so it doesn't come up very often. - Jonathan M Davis
Re: foreach for ranges?
On Tuesday, 17 July 2012 at 19:45:45 UTC, Jonathan M Davis wrote: This post gives the current precedence, but there was some discussion of adjusting it a bit: http://forum.dlang.org/post/mailman.275.1342019430.31962.digitalmars- d...@puremagic.com From the looks of it, opApply gets precedence right now. But mixing ranges and opApply isn't a good idea in most cases, so it doesn't come up very often. - Jonathan M Davis Ok, thanks !
Re: foreach for ranges?
Thanks for the reply. Not sure how I missed it there. Interesting that the compiler has to be made aware of a concept that I had thought was only supposed to be part of phobos. Would it be possible to implement it in std.range using the new UFCs? On Tuesday, 17 July 2012 at 19:17:47 UTC, Ali Çehreli wrote: On 07/17/2012 11:59 AM, Mike L. wrote: How exactly does the compiler know how to do foreach on ranges (for example, ones returned by std.algorithm.map ?) I've looked around in std.algorithm and std.range, but can't seem to figure it out. The spec mentions it under 'Foreach over Structs and Classes with Ranges': http://dlang.org/statement.html#ForeachStatement There are two methods: a) opApply() member functions (and opApplyReverse(), which is rumored to be deprecated in the future) b) empty, front, and popFront() member functions Ali
Re: foreach for ranges?
On Wednesday, July 18, 2012 06:27:28 Mike L. wrote: > Thanks for the reply. Not sure how I missed it there. Interesting > that the compiler has to be made aware of a concept that I had > thought was only supposed to be part of phobos. Would it be > possible to implement it in std.range using the new UFCs? You can do for(; !range.empty; range.popFront()) { auto e = range.front; } without the compiler doing anything at all. But if you want for(e; range) {} you need a way in the language for the compiler to translate that into the above. UFCS has nothing to do with it. All UFCS does is take a.b(c, d) and make it b(a, c, d). - Jonathan M Davi
Re: foreach for ranges?
On Wednesday, 18 July 2012 at 04:54:51 UTC, Jonathan M Davis wrote: On Wednesday, July 18, 2012 06:27:28 Mike L. wrote: Thanks for the reply. Not sure how I missed it there. Interesting that the compiler has to be made aware of a concept that I had thought was only supposed to be part of phobos. Would it be possible to implement it in std.range using the new UFCs? You can do for(; !range.empty; range.popFront()) { auto e = range.front; } without the compiler doing anything at all. But if you want for(e; range) {} you need a way in the language for the compiler to translate that into the above. UFCS has nothing to do with it. All UFCS does is take a.b(c, d) and make it b(a, c, d). - Jonathan M Davi If UFCS worked on operators, you would be able to make ranges without any compiler support. int opApply(T)(T Range) if(isInputRange!T) { // Stuff. }
Re: foreach for ranges?
On Wednesday, July 18, 2012 07:19:59 Kapps wrote: > If UFCS worked on operators, you would be able to make ranges > without any compiler support. > > int opApply(T)(T Range) if(isInputRange!T) { > // Stuff. > } You can't overload operators externally to a user-defined type. They must be part of the user-defined type that they operate on. Also, UFCS makes no sense on overloaded operators, because they don't get called with ".", and all UFCS is is changing obj.func(params) to func(obj, params). - Jonathan M Davis
Re: foreach for ranges?
Also, UFCS makes no sense on overloaded operators, because they don't get called with ".", and all UFCS is is changing obj.func(params) to func(obj, params). - Jonathan M Davis Ok, that's basically what I was wondering. I had assumed foreach(e; someThing) {} could possibly have been converted to someThing.opApply() . Thanks for clarifying.
Re: foreach for ranges?
On 07/18/2012 08:21 AM, Mike L. wrote: >> Also, UFCS makes no sense on overloaded operators, because they don't get >> called with ".", and all UFCS is is changing obj.func(params) to >> func(obj, >> params). >> >> - Jonathan M Davis > > Ok, that's basically what I was wondering. I had assumed foreach(e; > someThing) {} could possibly have been converted to someThing.opApply() > . Thanks for clarifying. But that is still true and opApply receives the body of the foreach loop as a delegate: someThing.opApply(delegate int(/* loop variables */) { // ... the body of foreach ... return terminationCode; // whether the user did 'break;' }); Also, the following bug (that is already fixed) is somewhat related to this discussion: http://d.puremagic.com/issues/show_bug.cgi?id=5605 Ali