www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - opApply ref and "const" iterators

reply gzp <galap freemail.hu> writes:
Hello,

Iám new to D so i might be all wrong. Given the code:

class Foo {
	int opApply( int delegate(ref real) dg ) {...} //A. 
	int opApply( int delegate(real) dg ) {...} // B,
}

...
	Foo foo = new Foo;
	foreach( a; foo ) {...}  // 1.
	foreach( ref a; foo ) {...} // 2,

Is it normal that, the A. version (with ref) is called for both cases and if
the A is eliminated, only the 2. foreach loop will compile ? The second case
works as i expected but what about the first case - the B. function won't be
called ever ?

Furthermore, i wanted to create a const iterator

class Foo {
	int opApply( int delegate(ref real) dg ) {...} //A. 
	const int opApply( int delegate(real) dg ) {...} // B,
}

...
	Foo foo = new Foo;
        const Foo f2 = foo;
	foreach( a; f2 ) {...}  // 1.
	foreach( ref a; foo ) {...} // 2,

It won't compile. (dmd 2.032) (I expected that, for the 1. loop the B version
and for the 2. loop the A version of the functions'd  be called) 

So what is the D way to create const iterator ?
Sep 28 2009
next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, Sep 28, 2009 at 6:58 PM, gzp <galap freemail.hu> wrote:
 Hello,

 I=E1m new to D so i might be all wrong. Given the code:

 class Foo {
 =A0 =A0 =A0 =A0int opApply( int delegate(ref real) dg ) {...} //A.
 =A0 =A0 =A0 =A0int opApply( int delegate(real) dg ) {...} // B,
 }

 ...
 =A0 =A0 =A0 =A0Foo foo =3D new Foo;
 =A0 =A0 =A0 =A0foreach( a; foo ) {...} =A0// 1.
 =A0 =A0 =A0 =A0foreach( ref a; foo ) {...} // 2,

 Is it normal that, the A. version (with ref) is called for both cases and=
if the A is eliminated, only the 2. foreach loop will compile ? The second= case works as i expected but what about the first case - the B. function w= on't be called ever ? Yes. For some reason the delegate that opApply takes must always take ref params, even if you don't iterate as such. This isn't really documented anywhere.
Sep 28 2009
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Tue, 29 Sep 2009 02:58:01 +0400, gzp <galap freemail.hu> wrote:

 Hello,

 I=C3=A1m new to D so i might be all wrong. Given the code:
Hello and welcome to the D world!
 class Foo {
 	int opApply( int delegate(ref real) dg ) {...} //A.
 	int opApply( int delegate(real) dg ) {...} // B,
 }

 ...
 	Foo foo =3D new Foo;
 	foreach( a; foo ) {...}  // 1.
 	foreach( ref a; foo ) {...} // 2,

 Is it normal that, the A. version (with ref) is called for both cases
I believe questions like this belong to D.learn newsgroup. I always wondered why is it so, too, but I never thought as being a bug = = about it. Perhaps, someone else may explain a reason behind it. You may create a = bugzilla ticket if no one will give an answer.
 and if the A is eliminated, only the 2. foreach loop will compile ?
I believe none of them will compile.
 The second case works as i expected but what about the first case - th=
e =
 B. function won't be called ever ?

 Furthermore, i wanted to create a const iterator

 class Foo {
 	int opApply( int delegate(ref real) dg ) {...} //A.
 	const int opApply( int delegate(real) dg ) {...} // B,
 }

 ...
 	Foo foo =3D new Foo;
         const Foo f2 =3D foo;
 	foreach( a; f2 ) {...}  // 1.
 	foreach( ref a; foo ) {...} // 2,

 It won't compile. (dmd 2.032) (I expected that, for the 1. loop the B =
=
 version and for the 2. loop the A version of the functions'd  be calle=
d)
 So what is the D way to create const iterator ?
Once again, a ref version (A) is called, which is not marked as const an= d = as such your code doesn't compile. Try marking it const, too, and it wil= l = pass.
Sep 28 2009
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 28 Sep 2009 18:58:01 -0400, gzp <galap freemail.hu> wrote:

 Hello,

 Iám new to D so i might be all wrong. Given the code:

 class Foo {
 	int opApply( int delegate(ref real) dg ) {...} //A.
 	int opApply( int delegate(real) dg ) {...} // B,
 }

 ...
 	Foo foo = new Foo;
 	foreach( a; foo ) {...}  // 1.
 	foreach( ref a; foo ) {...} // 2,

 Is it normal that, the A. version (with ref) is called for both cases  
 and if the A is eliminated, only the 2. foreach loop will compile ? The  
 second case works as i expected but what about the first case - the B.  
 function won't be called ever ?
This is an undocumented limitation of the foreach/opApply model. Here is what happens when you call foreach. foreach(real x; foo) { writeln(x); } The compiler creates a local function with some internal name, like FE1, then calls the opApply with that function. If you don't specify ref for the args, it factors out the ref. For example: int FE1(ref real _x) { auto x = _x; // auto generated code factors out reference // now the foreach body goes here writeln(x); // auto-generated return return 0; } // auto-generated call to opApply foo.opApply(&FE1); The factoring out of ref is to prevent you from having to write 2 delegate functions if you want to handle both cases, since the non-ref version is easy to implement in terms of the ref version. However, I think it is useful to be able to limit the code from allowing ref. See my already-reported enhancement for this issue: http://d.puremagic.com/issues/show_bug.cgi?id=2443
 Furthermore, i wanted to create a const iterator

 class Foo {
 	int opApply( int delegate(ref real) dg ) {...} //A.
 	const int opApply( int delegate(real) dg ) {...} // B,
 }

 ...
 	Foo foo = new Foo;
         const Foo f2 = foo;
 	foreach( a; f2 ) {...}  // 1.
 	foreach( ref a; foo ) {...} // 2,

 It won't compile. (dmd 2.032) (I expected that, for the 1. loop the B  
 version and for the 2. loop the A version of the functions'd  be called)

 So what is the D way to create const iterator ?
There is definitely some room for improvement on const opApply. http://d.puremagic.com/issues/show_bug.cgi?id=2442 I also have one other opApply enhancment which I think would help make code much more readable: http://d.puremagic.com/issues/show_bug.cgi?id=2498 Please vote for these issues so they are considered! -Steve
Sep 29 2009