www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - foreach for ranges?

reply "Mike L." <mike.linford.reg gmail.com> writes:
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.
Jul 17 2012
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Jul 17 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Jul 17 2012
prev sibling next sibling parent "Eyyub" <eyyub.pangearaion gmail.com> writes:
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 ?
Jul 17 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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 

- Jonathan M Davis
Jul 17 2012
prev sibling next sibling parent "Eyyub" <eyyub.pangearaion gmail.com> writes:
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

very often. - Jonathan M Davis

Ok, thanks !
Jul 17 2012
prev sibling next sibling parent "Mike L." <mike.linford.reg gmail.com> writes:
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

Jul 17 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Jul 17 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/18/2012 08:21 AM, Mike L. wrote:
 Also, UFCS makes no sense on overloaded operators, because they 


 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
Jul 18 2012
prev sibling next sibling parent "Kapps" <opantm2+spam gmail.com> writes:
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. }
Jul 17 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Jul 17 2012
prev sibling parent "Mike L." <mike.linford.reg gmail.com> writes:
 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.
Jul 18 2012