www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is there any reason to use non-ref foreach?

reply Dukc <ajieskola gmail.com> writes:
For me, it seems that for generality you should always add ref 
into foreach loop variable. The reason is this:

import std.experimental.all;

struct NoCopies
{    disable this(this);
     int payload;
}

void main()
{   auto range = new NoCopies[20];
     foreach(const ref el; range) el.payload.writeln;
}

Without ref qualifier in el, this won't work because it would 
make a copy. Unlike ref as a function argument, it does not 
enforce refness:

import std.experimental.all;

void main()
{   auto range = iota(20).map!(x => x + 2);
     foreach(const ref el; range) el.writeln;
}

This compiles, even though range elements are rvalues.

This seems to imply, for me, that for generality one should 
always use ref in foreach loop variables. If the vairable has to 
be guarded against changes, it should const ref, not unqualified.

But considering unqualified is the default, I am probably missing 
something here. Performance?
Aug 31 2018
next sibling parent reply bauss <jj_1337 live.dk> writes:
On Friday, 31 August 2018 at 09:59:20 UTC, Dukc wrote:
 For me, it seems that for generality you should always add ref 
 into foreach loop variable. The reason is this:

 import std.experimental.all;

 struct NoCopies
 {    disable this(this);
     int payload;
 }

 void main()
 {   auto range = new NoCopies[20];
     foreach(const ref el; range) el.payload.writeln;
 }

 Without ref qualifier in el, this won't work because it would 
 make a copy. Unlike ref as a function argument, it does not 
 enforce refness:

 import std.experimental.all;

 void main()
 {   auto range = iota(20).map!(x => x + 2);
     foreach(const ref el; range) el.writeln;
 }

 This compiles, even though range elements are rvalues.

 This seems to imply, for me, that for generality one should 
 always use ref in foreach loop variables. If the vairable has 
 to be guarded against changes, it should const ref, not 
 unqualified.

 But considering unqualified is the default, I am probably 
 missing something here. Performance?
It makes sense in your simplified examples, but in practice it doesn't, because it will depend on each situation, what type of data you're enumerating etc. And I bet you there are some gotchas using just ref. In reality you're micro-optimizing something that doesn't require it. Remember that basically the difference is this. foreach (i; values) { ... } for (int _ = 0; _ < values; _++) { auto i = values[_]; ... } VS foreach (ref i; values) { ... } for (int _ = 0; _ < values; _++) { auto i = &values[_]; ... } So basically ... Instead of copying the value, you're just copying the address. I can't see the benefit other than added complexity.
Aug 31 2018
next sibling parent James Blachly <james.blachly gmail.com> writes:
On Friday, 31 August 2018 at 12:52:17 UTC, bauss wrote:
 So basically ... Instead of copying the value, you're just 
 copying the address.

 I can't see the benefit other than added complexity.
I assume a benefit could be observed if you are copying a large struct instead of an int.
Aug 31 2018
prev sibling parent Dukc <ajieskola gmail.com> writes:
On Friday, 31 August 2018 at 12:52:17 UTC, bauss wrote:
 In reality you're micro-optimizing something that doesn't 
 require it.
I think you misunderstood. I wasn't trying to optimize, I was looking for a general way to iterate.
 I can't see the benefit other than added complexity.
I just explained it. Iterating by ref works with elements that have postblits disabled, iterating by value doesn't. I was wondering that if iterating by ref is the most general way to iterate, why it isn't the default? Is there some big implication in using it?
Aug 31 2018
prev sibling parent reply Andrea Fontana <nospam example.com> writes:
On Friday, 31 August 2018 at 09:59:20 UTC, Dukc wrote:
 For me, it seems that for generality you should always add ref 
 into foreach loop variable. The reason is this:
One good reason: https://forum.dlang.org/thread/dlhrrgvzmhladnphidei forum.dlang.org
Sep 03 2018
parent reply Dukc <ajieskola gmail.com> writes:
On Monday, 3 September 2018 at 13:34:36 UTC, Andrea Fontana wrote:
 On Friday, 31 August 2018 at 09:59:20 UTC, Dukc wrote:
 For me, it seems that for generality you should always add ref 
 into foreach loop variable. The reason is this:
One good reason: https://forum.dlang.org/thread/dlhrrgvzmhladnphidei forum.dlang.org
I am almost sure it will stay how it is, because of the sheer amount of breakage changing that would cause. I still agree that in princliple, the general way to iterate should be something else (auto ref?). But as with autodecoding, the present way is already in too wide use to be worth changing. But I think we need an official line to confirm whether one can use that without risking a deprectation.
Sep 04 2018
parent reply Andrea Fontana <nospam example.com> writes:
On Tuesday, 4 September 2018 at 07:06:43 UTC, Dukc wrote:
 On Monday, 3 September 2018 at 13:34:36 UTC, Andrea Fontana 
 wrote:
 On Friday, 31 August 2018 at 09:59:20 UTC, Dukc wrote:
 For me, it seems that for generality you should always add 
 ref into foreach loop variable. The reason is this:
One good reason: https://forum.dlang.org/thread/dlhrrgvzmhladnphidei forum.dlang.org
I am almost sure it will stay how it is, because of the sheer amount of breakage changing that would cause. I still agree that in princliple, the general way to iterate should be something else (auto ref?). But as with autodecoding, the present way is already in too wide use to be worth changing. But I think we need an official line to confirm whether one can use that without risking a deprectation.
Waiting for this to be merged: https://github.com/dlang/dmd/pull/8437
Sep 04 2018
parent Dukc <ajieskola gmail.com> writes:
On Tuesday, 4 September 2018 at 08:17:14 UTC, Andrea Fontana 
wrote:
 Waiting for this to be merged:
 https://github.com/dlang/dmd/pull/8437
Well, it seems Andrei has already approved the concept. well, THAT is a good reason to avoid this paradigm. Thanks for the info.
Sep 04 2018