www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to iterate using foreach on a class?

reply "Gary Willoughby" <dev nomad.so> writes:
I have a class which contains an array as a core collection of 
data. I want to pass an instance of this class to a foreach loop 
and iterate through the enclosed array. How do i do this? I've 
asked this before and got an answer but i can't find anything now.
Nov 01 2013
next sibling parent reply "simendsjo" <simendsjo gmail.com> writes:
On Friday, 1 November 2013 at 11:30:12 UTC, Gary Willoughby wrote:
 I have a class which contains an array as a core collection of 
 data. I want to pass an instance of this class to a foreach 
 loop and iterate through the enclosed array. How do i do this? 
 I've asked this before and got an answer but i can't find 
 anything now.
alias this on the underlying array, or implement opApply: http://dlang.org/statement.html
Nov 01 2013
next sibling parent "Gary Willoughby" <dev nomad.so> writes:
On Friday, 1 November 2013 at 11:35:03 UTC, simendsjo wrote:
 On Friday, 1 November 2013 at 11:30:12 UTC, Gary Willoughby 
 wrote:
 I have a class which contains an array as a core collection of 
 data. I want to pass an instance of this class to a foreach 
 loop and iterate through the enclosed array. How do i do this? 
 I've asked this before and got an answer but i can't find 
 anything now.
alias this on the underlying array, or implement opApply: http://dlang.org/statement.html
Ah that's it, opApply! ta.
Nov 01 2013
prev sibling parent reply "Gary Willoughby" <dev nomad.so> writes:
On Friday, 1 November 2013 at 11:35:03 UTC, simendsjo wrote:
 On Friday, 1 November 2013 at 11:30:12 UTC, Gary Willoughby 
 wrote:
 I have a class which contains an array as a core collection of 
 data. I want to pass an instance of this class to a foreach 
 loop and iterate through the enclosed array. How do i do this? 
 I've asked this before and got an answer but i can't find 
 anything now.
alias this on the underlying array
Alias this?
Nov 01 2013
parent "evilrat" <evilrat666 gmail.com> writes:
On Friday, 1 November 2013 at 11:39:15 UTC, Gary Willoughby wrote:
 On Friday, 1 November 2013 at 11:35:03 UTC, simendsjo wrote:
 On Friday, 1 November 2013 at 11:30:12 UTC, Gary Willoughby 
 wrote:
 I have a class which contains an array as a core collection 
 of data. I want to pass an instance of this class to a 
 foreach loop and iterate through the enclosed array. How do i 
 do this? I've asked this before and got an answer but i can't 
 find anything now.
alias this on the underlying array
Alias this?
alias this can be used to do implicit casting like this ----------------- void someFunc(int x) { ... } struct A { alias this someValue; int someValue; } void main() { A a = A(5); someFunc(a); // implicitly extracts 5 from struct A } --------------- as side note, alias this is not finished yet, so use with caution as it still allows only one alias this per class/struct
Nov 01 2013
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, November 01, 2013 12:30:10 Gary Willoughby wrote:
 I have a class which contains an array as a core collection of
 data. I want to pass an instance of this class to a foreach loop
 and iterate through the enclosed array. How do i do this? I've
 asked this before and got an answer but i can't find anything now.
In general, if you want to make something work with foreach, you either make it a range, or you give it an opSlice which returns a range (another alternative would be define opApply, but in general, code should be using the range primitives rather than opApply). Given that you're looking to iterate an array, and you presumably don't want the array to be consumed when iterating, the simplest would be to simply declare an opSlice on the class returns the array. e.g. class C { int[] foo; auto opSlice() { return foo; } } Then when you use the class in a foreach loop, it'll be sliced, and the return value of opSlice (the array in this case) will then be iterated over. - Jonathan M Davis
Nov 01 2013
next sibling parent "Gary Willoughby" <dev nomad.so> writes:
On Friday, 1 November 2013 at 11:41:52 UTC, Jonathan M Davis 
wrote:
 On Friday, November 01, 2013 12:30:10 Gary Willoughby wrote:
 I have a class which contains an array as a core collection of
 data. I want to pass an instance of this class to a foreach 
 loop
 and iterate through the enclosed array. How do i do this? I've
 asked this before and got an answer but i can't find anything 
 now.
In general, if you want to make something work with foreach, you either make it a range, or you give it an opSlice which returns a range (another alternative would be define opApply, but in general, code should be using the range primitives rather than opApply). Given that you're looking to iterate an array, and you presumably don't want the array to be consumed when iterating, the simplest would be to simply declare an opSlice on the class returns the array. e.g. class C { int[] foo; auto opSlice() { return foo; } } Then when you use the class in a foreach loop, it'll be sliced, and the return value of opSlice (the array in this case) will then be iterated over. - Jonathan M Davis
Hmmm, that's simpler too. ta.
Nov 01 2013
prev sibling parent reply "simendsjo" <simendsjo gmail.com> writes:
On Friday, 1 November 2013 at 11:41:52 UTC, Jonathan M Davis 
wrote:
 On Friday, November 01, 2013 12:30:10 Gary Willoughby wrote:
 I have a class which contains an array as a core collection of
 data. I want to pass an instance of this class to a foreach 
 loop
 and iterate through the enclosed array. How do i do this? I've
 asked this before and got an answer but i can't find anything 
 now.
In general, if you want to make something work with foreach, you either make it a range, or you give it an opSlice which returns a range (another alternative would be define opApply, but in general, code should be using the range primitives rather than opApply). Given that you're looking to iterate an array, and you presumably don't want the array to be consumed when iterating, the simplest would be to simply declare an opSlice on the class returns the array. e.g. class C { int[] foo; auto opSlice() { return foo; } } Then when you use the class in a foreach loop, it'll be sliced, and the return value of opSlice (the array in this case) will then be iterated over. - Jonathan M Davis
So we basically have 4 ways..? 1) popFront + front 2) opSlice 3) alias this 4) opApply
Nov 01 2013
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 1 November 2013 at 12:37:20 UTC, simendsjo wrote:
 2) opSlice
 3) alias this
arguably these are the same in the context of the foreach loop. Both just provide direct access to the underlying array.
Nov 01 2013
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
01-Nov-2013 16:43, John Colvin пишет:
 On Friday, 1 November 2013 at 12:37:20 UTC, simendsjo wrote:
 2) opSlice
 3) alias this
arguably these are the same in the context of the foreach loop. Both just provide direct access to the underlying array.
No quite. I'd say alias this is frankly a bad idea to provide iteration. In any case returning naked underlying array is most surely short-sighted. In short we have 2 ways: 1) Ranges 2) opApply And a couple of extra things on _top_ of that to keep in mind: 1) Implicit conversion -> hence alias this to a range/opApply type works 2) opSlice is called on foreach aggregate if it's not a range or doesn't have opApply by itself. -- Dmitry Olshansky
Nov 01 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/01/2013 08:32 AM, Dmitry Olshansky wrote:

 In short we have 2 ways:
 1) Ranges
 2) opApply
As another shameless plug, those foreach methods are included in this chapter: http://ddili.org/ders/d.en/foreach_opapply.html Ali
Nov 01 2013
next sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
Ali:

 As another shameless plug, those foreach methods are included in this
chapter:
 http://ddili.org/ders/d.en/foreach_opapply.htm<http://ddili.org/ders/d.en/foreach_opapply.html>
OMG. I just grokked opApply. *epiphany moment* Thanks a lot, Ali! I tried to get it for *years*!
Nov 01 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/01/2013 02:28 PM, Philippe Sigaud wrote:
 Ali:

 As another shameless plug, those foreach methods are included in this
chapter:
 http://ddili.org/ders/d.en/foreach_opapply.htm<http://ddili.org/ders/d.en/foreach_opapply.html>
OMG. I just grokked opApply. *epiphany moment* Thanks a lot, Ali! I tried to get it for *years*!
You made my day! :) I can't believe that the king of D templates learned something from my little chapter: https://github.com/PhilippeSigaud/D-templates-tutorial Ali
Nov 01 2013
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Fri, Nov 1, 2013 at 11:15 PM, Ali =C3=87ehreli <acehreli yahoo.com> wrot=
e:

 You made my day! :) I can't believe that the king of D templates learned
something from my little chapter: https://github.com/**PhilippeSigaud/D-templates-**tutorial<https://gith=
ub.com/PhilippeSigaud/D-templates-tutorial>
 ;-) You're too kind. I should dust this text somewhat.
My understanding of D templates is now years behind the compiler (see the new `alias Name(T) =3D ...` syntax in 2.064. That's cool). Anyway, back to opApply. I should write something using it before I forget how to use it :) What did you use to generate your website, btw?
Nov 01 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/01/2013 03:51 PM, Philippe Sigaud wrote:

 What did you use to generate your website, btw?
It is a completely static web site (except the Google translate widget) that is produced by ddoc and a couple of Makefiles. The following is the Turkish readme file: https://code.google.com/p/ddili/source/browse/trunk/BENIOKU The tools required for the site are just dmd and GNU make. The free pdf generator prince is used for the pdf versions of the books. I just do make test to produce the light-weight versions of the pages during development and make to produce a single tar file to upload to the provider. Ali
Nov 01 2013
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sat, Nov 2, 2013 at 12:08 AM, Ali =C3=87ehreli <acehreli yahoo.com> wrot=
e:

 On 11/01/2013 03:51 PM, Philippe Sigaud wrote:

 What did you use to generate your website, btw?
It is a completely static web site (except the Google translate widget) that is produced by ddoc and a couple of Makefiles.
This is something I'm looking for!
 The following is the Turkish readme file:

   https://code.google.com/p/**ddili/source/browse/trunk/**BENIOKU<https:/=
/code.google.com/p/ddili/source/browse/trunk/BENIOKU>
 The tools required for the site are just dmd and GNU make. The free pdf
 generator prince is used for the pdf versions of the books.

 I just do

   make test

 to produce the light-weight versions of the pages during development and

   make

 to produce a single tar file to upload to the provider.
OK, that seems quite similar to what I want. Any limitation you hit with Ddoc? Where can I get a view of the internal .ddoc file you used for the macro definitions? I found the source docs for your book text, but not the one containing definitions. I'm planning to write a new text on D, and though I'm enamoured of Markdown, I'm willing to give Ddoc a chance, since Andrei pushes its usage. I see three limitations: - almost no one knows Ddoc. Markdown is simple and used by the entire planet. - no possibility to inject equations with Ddoc? - no possibility to put images? (I may be wrong on this one). The equation requirement might seem strange, but I'd like to write a ray-tracing tutorial in D, and ray-tracing 'theory' uses a lot of maths. Many markdown parser know LaTeX or MathML. Mayby with MathML and invoking HTML code inside Ddoc? Oh, and if you could find the time to translate the turkish page, that would be great!
Nov 02 2013
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
I will respond later with more information. Here is just the quick ones. :)

On 11/02/2013 01:34 AM, Philippe Sigaud wrote:

 Where can I get a view of the internal .ddoc file you used for the macro
 definitions?
They are the ones that end with .ddoc here: https://code.google.com/p/ddili/source/browse/trunk/#trunk%2Fsrc and additionally in each book directory, e.g.: https://code.google.com/p/ddili/source/browse/trunk/#trunk%2Fsrc%2Fders%2Fd.en (Beware that there is some "technical debt" there. ;) ) Some ddoc files are auto generated by scripts such as this one: https://code.google.com/p/ddili/source/browse/trunk/src/make_ders_macros.sh That one deals with the Prev and Next links to point at the neighboring pages.
 - no possibility to inject equations with Ddoc?
I don't know anything about that. :(
 - no possibility to put images? (I may be wrong on this one).
By the IMG macro for img links like this one uses: https://code.google.com/p/ddili/source/browse/trunk/src/ders/d.en/pdf_indir.d#10
   Oh, and if you could find the time to translate the turkish page, that
 would be great!
To be continued... :) Ali
Nov 02 2013
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/02/2013 01:34 AM, Philippe Sigaud wrote:

 Any limitation you hit with Ddoc?
One annoyance is with parentheses in code sections. Ddoc allows using ddoc macros even in code section and I like it because I can highlight parts of code by a macro. However, that means that unbalanced parentheses in code sections cause trouble. For example (if I remember correctly), even a string like "1) blah" in a code section causes formatting issues. So, one has to use the equivalents of the following macros: OPEN_PAREN = &#40; CLOSE_PAREN = &#41; COMMA = &#44; DOLLAR = &#36;
 if you could find the time to translate the turkish page, that would be
 great!
http://code.google.com/p/ddili/source/browse/trunk/README Ali
Nov 03 2013
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Mon, Nov 4, 2013 at 6:05 AM, Ali =C3=87ehreli <acehreli yahoo.com> wrote=
:

 On 11/02/2013 01:34 AM, Philippe Sigaud wrote:

 Any limitation you hit with Ddoc?
One annoyance is with parentheses in code sections. Ddoc allows using ddo=
c
 macros even in code section and I like it because I can highlight parts o=
f
 code by a macro.
Yeah, I saw that in your code. I didn't know that could be done.
 However, that means that unbalanced parentheses in code sections cause
 trouble. For example (if I remember correctly), even a string like "1)
 blah" in a code section causes formatting issues. So, one has to use the
 equivalents of the following macros:

   OPEN_PAREN =3D &#40;
   CLOSE_PAREN =3D &#41;
   COMMA =3D &#44;
   DOLLAR =3D &#36;
I saw these and wondered what they were for. Why comma and dollar?
 if you could find the time to translate the turkish page, that would be
 great!
   http://code.google.com/p/ddili/source/browse/trunk/README
Ah, thanks you, Ali. I now realize I got only a small part of it.
Nov 03 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/03/2013 09:44 PM, Philippe Sigaud wrote:

    COMMA = &#44;
    DOLLAR = &#36;
I saw these and wondered what they were for. Why comma and dollar?
Actual comma inside a macro is taken as argument separator. From src/ders/d.en/operator_overloading.d: $(ROW3 slice to some elements, opSlice, collection[i$(VIRGUL) j]) (Note: VIRGUL is COMMA) If I used actual comma, " j]" would be taken as an unused extra parameter to ROW3. Dollar sign appears in dlang forum links. The only occurrence so far has been inside the Turkish translation of David Nadlinger's purity article, src/makale/saflik.d: $(LINK2 http://forum.dlang.org/thread/i7bp8o$(DOLAR)6po$(DOLAR)1 digitalmars.com, son değişikleri de getirmiş olan tartışma) Otherwise, the $ character would be parsed as the beginning of a macro. (Perhaps there is some sort of escaping but I just used the DOLAR macro. :-/) Ali
Nov 03 2013
prev sibling parent Johannes Pfau <nospam example.com> writes:
Am Fri, 01 Nov 2013 08:50:19 -0700
schrieb Ali =C3=87ehreli <acehreli yahoo.com>:

 On 11/01/2013 08:32 AM, Dmitry Olshansky wrote:
=20
 In short we have 2 ways:
 1) Ranges
 2) opApply
=20 As another shameless plug, those foreach methods are included in this=20 chapter: =20 http://ddili.org/ders/d.en/foreach_opapply.html =20 Ali =20
I just saw a small mistake on that page: ".popFront() must move to the element that is one before the end (skips the back element)" popFront should be popBack.
Nov 03 2013
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, November 01, 2013 19:32:35 Dmitry Olshansky wrote:
 01-Nov-2013 16:43, John Colvin пишет:
 On Friday, 1 November 2013 at 12:37:20 UTC, simendsjo wrote:
 2) opSlice
 3) alias this
arguably these are the same in the context of the foreach loop. Both just provide direct access to the underlying array.
No quite. I'd say alias this is frankly a bad idea to provide iteration. In any case returning naked underlying array is most surely short-sighted.
Pretty much anytime that you're tempted to use alias this, you should reconsider. It _does_ have its uses, but implicit conversions tend to cause a lot problems - especially in generic code. And in this case, you can simply declare opSlice to return the underlying array, so there isn't really any benefit to using alias this other than the fact that it saves you a few characters (which isn't even vaguely worth the cost IMHO).
 In short we have 2 ways:
 1) Ranges
 2) opApply
 
 And a couple of extra things on _top_ of that to keep in mind:
 1) Implicit conversion -> hence alias this to a range/opApply type works
 2) opSlice is called on foreach aggregate if it's not a range or doesn't
 have opApply by itself.
Yeah. Any user-defined type that's iterable via foreach uses either the range API or opApply. And in general, unless the range API isn't going to work for you, it's recommended to use the range API rather than opApply. opSlice comes into play when you want to iterate over something as a range without consuming it. The most common place to see opSlice would likely be on containers. - Jonathan M Davis
Nov 01 2013
prev sibling parent reply "Nicolas Sicard" <dransic gmail.com> writes:
On Friday, 1 November 2013 at 12:37:20 UTC, simendsjo wrote:
 On Friday, 1 November 2013 at 11:41:52 UTC, Jonathan M Davis 
 wrote:
 On Friday, November 01, 2013 12:30:10 Gary Willoughby wrote:
 I have a class which contains an array as a core collection of
 data. I want to pass an instance of this class to a foreach 
 loop
 and iterate through the enclosed array. How do i do this? I've
 asked this before and got an answer but i can't find anything 
 now.
In general, if you want to make something work with foreach, you either make it a range, or you give it an opSlice which returns a range (another alternative would be define opApply, but in general, code should be using the range primitives rather than opApply). Given that you're looking to iterate an array, and you presumably don't want the array to be consumed when iterating, the simplest would be to simply declare an opSlice on the class returns the array. e.g. class C { int[] foo; auto opSlice() { return foo; } } Then when you use the class in a foreach loop, it'll be sliced, and the return value of opSlice (the array in this case) will then be iterated over. - Jonathan M Davis
So we basically have 4 ways..? 1) popFront + front 2) opSlice 3) alias this 4) opApply
How about having a nested struct implementing a range interface + a method ( property) returning it + alias this on the property? http://dpaste.dzfl.pl/230061d2
Nov 03 2013
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, November 03, 2013 14:28:13 Nicolas Sicard wrote:
 So we basically have 4 ways..?
 1) popFront + front
 2) opSlice
 3) alias this
 4) opApply
How about having a nested struct implementing a range interface + a method ( property) returning it + alias this on the property? http://dpaste.dzfl.pl/230061d2
alias this should be avoided as much as possible. It's a bug magnet - especilaly when generic code is involved. And there's no reason to create a new range type in this case, because all that needs to be iterated over is the array. It makes by far the most sense to simply treat the class as a container, and overload opSlice so that it returns the array to be iterated over. If there was ever a need to do something more complicated than just iterate over the array, then a new range type could be returned from opSlice instead, but as it stands simply returning the array would be just fine. - Jonathan M Davis
Nov 05 2013