Jump to page: 1 2
Thread overview
How do I make my class iterable?
Jun 22, 2015
Assembly
Jun 22, 2015
q66
Jun 22, 2015
Ali Çehreli
Jun 22, 2015
Assembly
Jun 22, 2015
Assembly
Jun 22, 2015
anonymous
Jun 23, 2015
Assembly
Jun 22, 2015
Ali Çehreli
Jun 22, 2015
Assembly
Jun 22, 2015
Ali Çehreli
June 22, 2015
Does D has an equivalent to C#'s iterator (https://msdn.microsoft.com/en-us/library/65zzykke.aspx)? if so, where can I find it?

What I want is loop over a user-defined class/struct. In case of C#, I just implement the IEnumerable and the GetEnumerator() methods that's called by the foreach() construct together with the yield keyword I "feed" the loop until the moveNext() returns false (no next element). The think I've linked has some C# code example.

 Something like this:

struct MyStruct
{
   // proper methods/proeperties called by foreach() to iterate
   // over the array
   int[] myarr;
   int = 0;
   int getNext() { return myarr[i]; }
   bool hasNext() { return i == myarr.length; }
}

MyStruct s;
foreach(MyStruct x; s)
{

}

Is this possible?



June 22, 2015
On Monday, 22 June 2015 at 16:33:43 UTC, Assembly wrote:
> Does D has an equivalent to C#'s iterator (https://msdn.microsoft.com/en-us/library/65zzykke.aspx)? if so, where can I find it?
>
> What I want is loop over a user-defined class/struct. In case of C#, I just implement the IEnumerable and the GetEnumerator() methods that's called by the foreach() construct together with the yield keyword I "feed" the loop until the moveNext() returns false (no next element). The think I've linked has some C# code example.
>
>  Something like this:
>
> struct MyStruct
> {
>    // proper methods/proeperties called by foreach() to iterate
>    // over the array
>    int[] myarr;
>    int = 0;
>    int getNext() { return myarr[i]; }
>    bool hasNext() { return i == myarr.length; }
> }
>
> MyStruct s;
> foreach(MyStruct x; s)
> {
>
> }
>
> Is this possible?

use opApply.
June 22, 2015
On 06/22/2015 09:37 AM, q66 wrote:

> use opApply.

Yes. Additionally, an InputRange interface can be used:

  http://ddili.org/ders/d.en/foreach_opapply.html

Ali

June 22, 2015
On Monday, 22 June 2015 at 16:52:15 UTC, Ali Çehreli wrote:
> On 06/22/2015 09:37 AM, q66 wrote:
>
>> use opApply.
>
> Yes. Additionally, an InputRange interface can be used:
>
>   http://ddili.org/ders/d.en/foreach_opapply.html
>
> Ali

I was reading exaclty this page that.

I've had implmented this method/properties (I remembered how foreach() is translated to for() by the compiler using front/popFront() and such):

T front() { return _app.data[index]; }
T front(int index, T a) { return _app.data[index]; }


	void popFront()
	{
		index++;
	}


and called like this:

foreach(int i, MyType p; places) {

but I get this error:

Error: cannot infer argument types, expected 1 argument, not 2

to try solve that error I added the overload method:

T front(int index, T a)

but it didn't worked. How do I solve this?
June 22, 2015
On 6/22/15 1:03 PM, Assembly wrote:
> On Monday, 22 June 2015 at 16:52:15 UTC, Ali Çehreli wrote:
>> On 06/22/2015 09:37 AM, q66 wrote:
>>
>>> use opApply.
>>
>> Yes. Additionally, an InputRange interface can be used:
>>
>>   http://ddili.org/ders/d.en/foreach_opapply.html
>>
>> Ali
>
> I was reading exaclty this page that.
>
> I've had implmented this method/properties (I remembered how foreach()
> is translated to for() by the compiler using front/popFront() and such):
>
> T front() { return _app.data[index]; }
> T front(int index, T a) { return _app.data[index]; }
>
>
>      void popFront()
>      {
>          index++;
>      }
>
>
> and called like this:
>
> foreach(int i, MyType p; places) {
>
> but I get this error:
>
> Error: cannot infer argument types, expected 1 argument, not 2
>
> to try solve that error I added the overload method:
>
> T front(int index, T a)
>
> but it didn't worked. How do I solve this?

TBH, opApply is much better suited to classes.

But in order to have multiple parameters with foreach by using a range, you must return a tuple:

auto front() { import std.typecons: tuple; return tuple(index, _app.data[index]);}

Note, do NOT do this on your class, you should be creating a range struct type, and return the range from opIndex() with no parameters.

-Steve
June 22, 2015
On 06/22/2015 10:03 AM, Assembly wrote:

> foreach(int i, MyType p; places) {
>
> but I get this error:
>
> Error: cannot infer argument types, expected 1 argument, not 2

Yeah, the loop counter is automatic only for slices. You can use 'enumerate' for other types:

    foreach (i, element; NumberRange(42, 47).enumerate) {
        // ...
    }

That is taken from the same page: ;)


http://ddili.org/ders/d.en/foreach_opapply.html#ix_foreach_opapply.loop%20counter

Ali

June 22, 2015
On Monday, 22 June 2015 at 17:09:16 UTC, Steven Schveighoffer wrote:
> On 6/22/15 1:03 PM, Assembly wrote:
>> [...]
>
> TBH, opApply is much better suited to classes.
>
> But in order to have multiple parameters with foreach by using a range, you must return a tuple:
>
> auto front() { import std.typecons: tuple; return tuple(index, _app.data[index]);}
>
> Note, do NOT do this on your class, you should be creating a range struct type, and return the range from opIndex() with no parameters.
>
> -Steve

I'm using this, thanks for all. Can someone clarify how does opApply() works? I assume it's called every iteration and as opApply() has a loop does it means the number of iteration ran actually is the ones from foreach() is 2*n where n is the number of elements in the array, is this right?
June 22, 2015
On Monday, 22 June 2015 at 18:07:36 UTC, Ali Çehreli wrote:
> On 06/22/2015 10:03 AM, Assembly wrote:
>
> > foreach(int i, MyType p; places) {
> >
> > but I get this error:
> >
> > Error: cannot infer argument types, expected 1 argument, not 2
>
> Yeah, the loop counter is automatic only for slices. You can use 'enumerate' for other types:
>
>     foreach (i, element; NumberRange(42, 47).enumerate) {
>         // ...
>     }
>
> That is taken from the same page: ;)
>
>
> http://ddili.org/ders/d.en/foreach_opapply.html#ix_foreach_opapply.loop%20counter
>
> Ali

if my opApply() is defiend as the following:

int opApply(int delegate(ref int, ref T) del)
	{
		int result;

		foreach(int i, T val; _app.data)
		{
			result = del(i, _app.data[i]);
			
			if(result)
				break;
		}

		return result;
	}

and called like:

foreach(int i, MyType p; places) {

isn't i the loop counter?
June 22, 2015
On 06/22/2015 11:48 AM, Assembly wrote:

> if my opApply() is defiend as the following:
>
> int opApply(int delegate(ref int, ref T) del)
>      {
[...]
>      }
>
> and called like:
>
> foreach(int i, MyType p; places) {
>
> isn't i the loop counter?

size_t is more natural but yes, that's it.

Ali

June 22, 2015
On Monday, 22 June 2015 at 18:44:22 UTC, Assembly wrote:
> I'm using this, thanks for all. Can someone clarify how does opApply() works? I assume it's called every iteration and as opApply() has a loop does it means the number of iteration ran actually is the ones from foreach() is 2*n where n is the number of elements in the array, is this right?

opApply is called only once. The body of the foreach is passed to opApply as a delegate. The opApply implementation runs the supplied foreach body, possibly in a loop. Every such call is an iteration of the foreach loop.

With opApply this:
    foreach(x; iterable) {/* do something with x */}
gets rewritten to this:
    iterable.opApply((x) {/* do something with x */});
« First   ‹ Prev
1 2