Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 22, 2015 How do I make my class iterable? | ||||
---|---|---|---|---|
| ||||
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 Re: How do I make my class iterable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Assembly | 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 Re: How do I make my class iterable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to q66 | 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 Re: How do I make my class iterable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 Re: How do I make my class iterable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Assembly | 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 Re: How do I make my class iterable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Assembly | 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 Re: How do I make my class iterable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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 Re: How do I make my class iterable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 Re: How do I make my class iterable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Assembly | 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 Re: How do I make my class iterable? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Assembly | 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 */});
|
Copyright © 1999-2021 by the D Language Foundation