www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - opApply- and foreach-reverse request

reply James Dunne <jdunne4 bradley.edu> writes:
I'd like to request an opApply-reverse operator and a new foreach-reverse
construct (syntax up for discussion, don't flame me for my -reverse's).

Possible syntax:  opApplyReverse and foreachreverse (or just foreachr)

This would be especially useful for some lists you need to iterate through in
reverse.  You could have both the forward iterator and reverse iterator versions
in the same class.

I came across this while coding with DFL.  I need to delete the selected items
from a ListBox control.  The ListBox offers a property called selectedIndices(),
and if you delete them in order, all the indices after the one you just deleted
become invalid (shifted up by one).  The correct way to do it would be to
reverse iterate through the selectedIndices and delete them.  That way no
indices would be invalid after you delete them.

Anyone else think this would be a valuable addition to D?

Regards,
James Dunne
Feb 23 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 23 Feb 2005 23:21:02 +0000 (UTC), James Dunne  
<jdunne4 bradley.edu> wrote:
 I'd like to request an opApply-reverse operator and a new foreach-reverse
 construct (syntax up for discussion, don't flame me for my -reverse's).

 Possible syntax:  opApplyReverse and foreachreverse (or just foreachr)

 This would be especially useful for some lists you need to iterate  
 through in
 reverse.  You could have both the forward iterator and reverse iterator  
 versions
 in the same class.

 I came across this while coding with DFL.  I need to delete the selected  
 items
 from a ListBox control.  The ListBox offers a property called  
 selectedIndices(),
 and if you delete them in order, all the indices after the one you just  
 deleted
 become invalid (shifted up by one).  The correct way to do it would be to
 reverse iterate through the selectedIndices and delete them.  That way no
 indices would be invalid after you delete them.

 Anyone else think this would be a valuable addition to D?

Can't you go.. array = listBox.selectedIndices().dup; foreach(Item i; array.reverse) { } http://www.digitalmars.com/d/arrays.html "reverse" - "Reverses in place the order of the elements in the array. Returns the array." or, are you asking whether we want/need an operator or foreach instead? Regan
Feb 23 2005
parent reply James Dunne <jdunne4 bradley.edu> writes:
In article <opsmocl1lz23k2f5 ally>, Regan Heath says...
On Wed, 23 Feb 2005 23:21:02 +0000 (UTC), James Dunne  
<jdunne4 bradley.edu> wrote:
 I'd like to request an opApply-reverse operator and a new foreach-reverse
 construct (syntax up for discussion, don't flame me for my -reverse's).

 Possible syntax:  opApplyReverse and foreachreverse (or just foreachr)

 This would be especially useful for some lists you need to iterate  
 through in
 reverse.  You could have both the forward iterator and reverse iterator  
 versions
 in the same class.

 I came across this while coding with DFL.  I need to delete the selected  
 items
 from a ListBox control.  The ListBox offers a property called  
 selectedIndices(),
 and if you delete them in order, all the indices after the one you just  
 deleted
 become invalid (shifted up by one).  The correct way to do it would be to
 reverse iterate through the selectedIndices and delete them.  That way no
 indices would be invalid after you delete them.

 Anyone else think this would be a valuable addition to D?


Can't you go..

array = listBox.selectedIndices().dup;
foreach(Item i; array.reverse) {
}

Not for a class. dup is a property of arrays. The function selectedIndices() returns a class called SelectedIndexCollection which has opApply overloaded.
http://www.digitalmars.com/d/arrays.html
"reverse" - "Reverses in place the order of the elements in the array.  
Returns the array."

or, are you asking whether we want/need an operator or foreach instead?

We would need both opApplyReverse and foreachreverse in order to have it; I'm not sure I understand your question.
Regan

Regards, James Dunne
Feb 23 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 24 Feb 2005 00:13:19 +0000 (UTC), James Dunne  
<jdunne4 bradley.edu> wrote:
 In article <opsmocl1lz23k2f5 ally>, Regan Heath says...
 On Wed, 23 Feb 2005 23:21:02 +0000 (UTC), James Dunne
 <jdunne4 bradley.edu> wrote:
 I'd like to request an opApply-reverse operator and a new  
 foreach-reverse
 construct (syntax up for discussion, don't flame me for my -reverse's).

 Possible syntax:  opApplyReverse and foreachreverse (or just foreachr)

 This would be especially useful for some lists you need to iterate
 through in
 reverse.  You could have both the forward iterator and reverse iterator
 versions
 in the same class.

 I came across this while coding with DFL.  I need to delete the  
 selected
 items
 from a ListBox control.  The ListBox offers a property called
 selectedIndices(),
 and if you delete them in order, all the indices after the one you just
 deleted
 become invalid (shifted up by one).  The correct way to do it would be  
 to
 reverse iterate through the selectedIndices and delete them.  That way  
 no
 indices would be invalid after you delete them.

 Anyone else think this would be a valuable addition to D?


 Can't you go..

 array = listBox.selectedIndices().dup;
 foreach(Item i; array.reverse) {
 }

Not for a class. dup is a property of arrays. The function selectedIndices() returns a class called SelectedIndexCollection which has opApply overloaded.

Ahh. ok. I see. Ok, in order to be symetrical with an array, should it have a reverse method i.e. c = listBox.selectedIndices().reverse; foreach(Item i; c) { } Granted, a way to iterate backwards, or every 2nd,3rd,4th item .. without having to make a copy of the container would be useful and efficient.
 http://www.digitalmars.com/d/arrays.html
 "reverse" - "Reverses in place the order of the elements in the array.
 Returns the array."

 or, are you asking whether we want/need an operator or foreach instead?

We would need both opApplyReverse and foreachreverse in order to have it; I'm not sure I understand your question.

I didn't realise your reply above, my question isn't relevant now :) Regan
Feb 23 2005
parent reply James Dunne <jdunne4 bradley.edu> writes:
In article <opsmoeedwu23k2f5 ally>, Regan Heath says...
On Thu, 24 Feb 2005 00:13:19 +0000 (UTC), James Dunne  
<jdunne4 bradley.edu> wrote:
 In article <opsmocl1lz23k2f5 ally>, Regan Heath says...
 Can't you go..

 array = listBox.selectedIndices().dup;
 foreach(Item i; array.reverse) {
 }

Not for a class. dup is a property of arrays. The function selectedIndices() returns a class called SelectedIndexCollection which has opApply overloaded.

Ahh. ok. I see. Ok, in order to be symetrical with an array, should it have a reverse method i.e. c = listBox.selectedIndices().reverse; foreach(Item i; c) { }

What does a class want to reverse? I know what you mean, but in a general sense, it's not very clear.
Granted, a way to iterate backwards, or every 2nd,3rd,4th item .. without  
having to make a copy of the container would be useful and efficient.

Exactly: without having to make a copy. foreachreverse would be implemented for arrays automatically, instead of having to use .dup .reverse. It's an in-place reverse iteration and won't cost any more than a forward iteration. There's really no reason not to have it. A foreachreverse (or whatever the syntax would be) would look much clearer to the naked eye that you are in fact reverse iterating through a class/array/struct. Regards, James Dunne
Feb 23 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 24 Feb 2005 02:53:44 +0000 (UTC), James Dunne  
<jdunne4 bradley.edu> wrote:
 In article <opsmoeedwu23k2f5 ally>, Regan Heath says...
 On Thu, 24 Feb 2005 00:13:19 +0000 (UTC), James Dunne
 <jdunne4 bradley.edu> wrote:
 In article <opsmocl1lz23k2f5 ally>, Regan Heath says...
 Can't you go..

 array = listBox.selectedIndices().dup;
 foreach(Item i; array.reverse) {
 }

Not for a class. dup is a property of arrays. The function selectedIndices() returns a class called SelectedIndexCollection which has opApply overloaded.

Ahh. ok. I see. Ok, in order to be symetrical with an array, should it have a reverse method i.e. c = listBox.selectedIndices().reverse; foreach(Item i; c) { }

What does a class want to reverse? I know what you mean, but in a general sense, it's not very clear.

I wasn't trying to imply all classes need one, or even all containers. Those classes that act as containers might want one, if it makes sense to reverse the contents of the container. eg. like it does for arrays, but not associative ones.
 Granted, a way to iterate backwards, or every 2nd,3rd,4th item ..  
 without
 having to make a copy of the container would be useful and efficient.

Exactly: without having to make a copy. foreachreverse would be implemented for arrays automatically, instead of having to use .dup .reverse. It's an in-place reverse iteration and won't cost any more than a forward iteration. There's really no reason not to have it.

I agree. You can still hand code it with a for loop, assuming that is, that you can access the items with [] and you know the last index. The idea behind foreach is to avoid having to code specifically for the container type. i.e. indexes, linklist etc. I think this, or similar idea, is required to achieve that goal.
 A foreachreverse (or whatever the syntax would be) would look much  
 clearer to
 the naked eye that you are in fact reverse iterating through a
 class/array/struct.

foreach_r() maybe. Does the term "foreach" imply any direction forward or backward? To me it doesn't. I realise it's used in other languages, the same as in D, so it has a commonly understood meaning. I think the options are: - leave foreach, invent a backwards term i.e. foreach_r. - invent new terms, one for forward, one for backward. - add the ability to specify the 'step' in foreach Regan
Feb 23 2005
parent reply James Dunne <jdunne4 bradley.edu> writes:
In article <opsmol1osx23k2f5 ally>, Regan Heath says...
Does the term "foreach" imply any direction forward or backward? To me it  
doesn't. I realise it's used in other languages, the same as in D, so it  
has a commonly understood meaning.

I think the options are:

- leave foreach, invent a backwards term i.e. foreach_r.
- invent new terms, one for forward, one for backward.
- add the ability to specify the 'step' in foreach


Regan

I agree with the options listed, and really they're not up to me to decide ;). On specifying the 'step' for the foreach, that doesn't seem especially useful unless it's either +1 or -1, which I'm sure is what your point was. I'm just saying I don't see why anyone would use a container to foreach through on a specified interval bigger than one. Maybe a punny syntax like "foreach" is short for forward-each, and we could have "backeach". foreach to me seems to imply order, and is usually implemented as a forward iteration. It would be clearer to specify new terms, one for forward, one for backward, but so much D code exists using 'foreach' and it'd be a pain to go thru and change all that. It's wisest to keep 'foreach' and 'opApply' and just add new terms for the reverse. 'foreach_r' seems appealing to me. opApply_r, on the other hand, does not. The other functions opAdd_r, etc. are used to handle cases where the first argument is not the 'this' pointer of the class, not to "reversely add" something, whatever that means ;). I'd suggest opApplyReverse in this case. Regards, James Dunne
Feb 23 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 24 Feb 2005 03:41:02 +0000 (UTC), James Dunne  
<jdunne4 bradley.edu> wrote:
 In article <opsmol1osx23k2f5 ally>, Regan Heath says...
 Does the term "foreach" imply any direction forward or backward? To me  
 it
 doesn't. I realise it's used in other languages, the same as in D, so it
 has a commonly understood meaning.

 I think the options are:

 - leave foreach, invent a backwards term i.e. foreach_r.
 - invent new terms, one for forward, one for backward.
 - add the ability to specify the 'step' in foreach


 Regan

I agree with the options listed, and really they're not up to me to decide ;). On specifying the 'step' for the foreach, that doesn't seem especially useful unless it's either +1 or -1, which I'm sure is what your point was.

Actually, I was being intentionally vague :)
 I'm just
 saying I don't see why anyone would use a container to foreach through  
 on a
 specified interval bigger than one.

Isn't it the same reason someone would use a for loop with i+=2, or i-=2? Of course in addition to the step you need some way to indicate where to start start, end, x. That is, unless you assume -1 means start at the end, and +1 means start at the beginning and that no-one ever wants to start elsewhere. I think the concept of direction and step can apply to arrays, linklists, and other types of containers, if so does that mean foreach should handle them?
 Maybe a punny syntax like "foreach" is short for forward-each

I thought it was "for each" as in "for each item in .."
 , and we could have
 "backeach".  foreach to me seems to imply order, and is usually  
 implemented as a
 forward iteration.

I suspected that to others it might imply order.
 It would be clearer to specify new terms, one for forward,
 one for backward, but so much D code exists using 'foreach' and it'd be  
 a pain
 to go thru and change all that.

That was sort of my conclusion also.
 It's wisest to keep 'foreach' and 'opApply' and just add new terms for  
 the
 reverse. 'foreach_r' seems appealing to me.

Assuming there is no reason to want step then this option seems the best to me.
 opApply_r, on the other hand, does
 not.  The other functions opAdd_r, etc. are used to handle cases where  
 the first
 argument is not the 'this' pointer of the class, not to "reversely add"
 something, whatever that means ;).  I'd suggest opApplyReverse in this  
 case.

I didn't think about the naming of opApply. Regan
Feb 23 2005
parent reply James Dunne <jdunne4 bradley.edu> writes:
In article <opsmooadap23k2f5 ally>, Regan Heath says...
On Thu, 24 Feb 2005 03:41:02 +0000 (UTC), James Dunne  
<jdunne4 bradley.edu> wrote:
 In article <opsmol1osx23k2f5 ally>, Regan Heath says...
 Does the term "foreach" imply any direction forward or backward? To me  
 it
 doesn't. I realise it's used in other languages, the same as in D, so it
 has a commonly understood meaning.

 I think the options are:

 - leave foreach, invent a backwards term i.e. foreach_r.
 - invent new terms, one for forward, one for backward.
 - add the ability to specify the 'step' in foreach


 Regan

I agree with the options listed, and really they're not up to me to decide ;). On specifying the 'step' for the foreach, that doesn't seem especially useful unless it's either +1 or -1, which I'm sure is what your point was.

Actually, I was being intentionally vague :)
 I'm just
 saying I don't see why anyone would use a container to foreach through  
 on a
 specified interval bigger than one.

Isn't it the same reason someone would use a for loop with i+=2, or i-=2?

Not necessarily. Foreach was created to iterate through lists. for() was meant to give flexible looping ability. If you want to skip indicies, use a regular for() loop. Any well-implemented class that implements opApply (foreach support) should also implement opIndex to give access to individual elements. Besides, adding a step, start, and end to the current foreach syntax has the possibility of breaking code as it stands now. However, they could be optional arguments and not break anything, or they could be an optionally allowed syntax in addition to the "old (current) way".
Of course in addition to the step you need some way to indicate where to  
start start, end, x.

That is, unless you assume -1 means start at the end, and +1 means start  
at the beginning and that no-one ever wants to start elsewhere.

I think the concept of direction and step can apply to arrays, linklists,  
and other types of containers, if so does that mean foreach should handle  
them?

If you can give me a legitimate example where you would *need* to skip elements on a constant step using foreach, then I'll agree with you. I just can't think of any off-hand.
 Maybe a punny syntax like "foreach" is short for forward-each

I thought it was "for each" as in "for each item in .."

That's technically what it means, yes. But I was just throwing in the pun of foreach breaking up as "forward" and "each" to allow a backeach meaning "back" and "each". Just a dumb pun, don't worry about it ;)
 , and we could have
 "backeach".  foreach to me seems to imply order, and is usually  
 implemented as a
 forward iteration.

I suspected that to others it might imply order.

And it does. When you foreach through a D array, you iterate forward through it. It's just generally accepted that it has a forward order to it. In other languages (e.g. PHP, Perl, C#) this is true as well.
 It would be clearer to specify new terms, one for forward,
 one for backward, but so much D code exists using 'foreach' and it'd be  
 a pain
 to go thru and change all that.

That was sort of my conclusion also.

Excellent!
 It's wisest to keep 'foreach' and 'opApply' and just add new terms for  
 the
 reverse. 'foreach_r' seems appealing to me.

Assuming there is no reason to want step then this option seems the best to me.
 opApply_r, on the other hand, does
 not.  The other functions opAdd_r, etc. are used to handle cases where  
 the first
 argument is not the 'this' pointer of the class, not to "reversely add"
 something, whatever that means ;).  I'd suggest opApplyReverse in this  
 case.

I didn't think about the naming of opApply.

I just threw it out there, since it goes hand-in-hand with foreach. If we want to throw consistency and clarity out the window, opApply_r would be acceptable (and probably favorable to opApplyReverse). Regards, James Dunne
Feb 23 2005
next sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 I think the options are:
 - add the ability to specify the 'step' in foreach




 Not necessarily.  Foreach was created to iterate through lists.  for() was 
 meant
 to give flexible looping ability.  If you want to skip indicies, use a 
 regular
 for() loop.  Any well-implemented class that implements opApply (foreach
 support) should also implement opIndex to give access to individual 
 elements.

Though [] indexing can be very slow in the middle of a linked list.
 Besides, adding a step, start, and end to the current foreach syntax has 
 the
 possibility of breaking code as it stands now.  However, they could be 
 optional
 arguments and not break anything, or they could be an optionally allowed 
 syntax
 in addition to the "old (current) way".

Start and stop is not needed since that is what slicing is for. Stepping (I'm including reverse as the special case step = -1) is the only thing that isn't possible today without a "for" loop. This might have been proposed before- I can't remember. I think the following syntax is backwards compatible: foreach (ForeachTypeList; Expression [;Expression]) Statement where the optional second expression is the step. If the step is specified the opApply signature must match int opApply(int delegate(inout Type [, ...]) dg, int step); If there isn't an opApply with a step parameter it is an error. If the step is negative the traversal is backwards. Using a negative step as reverse means it is potentially a run-time decision. Also it isn't as explicit as having the word "reverse" or "backwards" or "_r" in there somewhere. But it would be nice to kill a few birds with one stone and it closely resembles how a for loop looks: for(start; stop; step) {...} foreach(iterator; container; step) {...}
Feb 24 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote:

[...]
 foreach(iterator; container; step) {...}

I am really stunned of this thread. I never heard of a construct in a meta language where "for each" is used without the meaning that whatever follows is to be interpreted as a set of items without any particular order. Am I out of bounds in this case? Can you show me an example where such thing is really used --- and of benefit? And please do not come with the example of a dictator who wants to shoot down every `step'th member of a town or elsewise defined group of people. -manfred
Feb 25 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Manfred Nowak" <svv1999 hotmail.com> wrote in message 
news:cvn4bb$j49$1 digitaldaemon.com...
 "Ben Hinkle" <ben.hinkle gmail.com> wrote:

 [...]
 foreach(iterator; container; step) {...}

I am really stunned of this thread. I never heard of a construct in a meta language where "for each" is used without the meaning that whatever follows is to be interpreted as a set of items without any particular order.

That's a legit view. I've always viewed foreach as another kind of for loop - one that handles tree traversals more cleanly than using STL-style iterators. The "each" in "foreach" indicates we go through a bunch of items, as you suggest, but I never got the impressions of any more semantics than that. I don't the see the usefulness of a step other than 1 or -1 for trees, though. but for lists of things it would be handy.
 Am I out of bounds in this case?

There is no spoon.
 Can you show me an
 example where such thing is really used --- and of benefit? And
 please do not come with the example of a dictator who wants to shoot
 down every `step'th member of a town or elsewise defined group of
 people.

 -manfred

I'll give an example from MATLAB. It is common to pass around string-value lists like ['Color', 'red', 'LineWidth', 2.4, 'LineStyle', ,'--'] and then have code that runs down the strings or values by stepping by 2. An example closer to D would be having a list of points in a polygon and wanting to draw only every 3rd point for increased performance.
Feb 25 2005
parent Manfred Nowak <svv1999 hotmail.com> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote:

[...]
 I don't the see the
 usefulness of a step other than 1 or -1 for trees, though. but
 for lists of things it would be handy.

For trees without any ordering of the nodes there are only two natural traversals: breadth-first and depth-first and none of them maps to an integer in a natural way. If the tree is implemented as linked cells of an array, then there are two more "natural" traversals defined by the ordering of the cells of the array. And whenever I say "for each node in tree" I mean that the choosen traversal is unimportant, that is in addition to the free choosing of the traversal any permutations of the elements is allowed. The same holds for lists. Whenever the order does matter you have to describe how to choose the next element and that is done be a `for'-loop. On which criteria has the decision to be made to a `for' or a `foreach' if both have nearly identical semantics?
 I'll give an example from MATLAB. It is common to pass around
 string-value lists like ['Color', 'red', 'LineWidth', 2.4,
 'LineStyle', ,'--'] and then have code that runs down the
 strings or values by stepping by 2. 
 
 An example closer to D would be having a list of points in a
 polygon and wanting to draw only every 3rd point for increased
 performance. 

Thanks. But in both examples the order of the items does matter. And in the second example you said "every" not "each". SO it looks like you are talking about a new iterative statement `forevery' with a step-clause --- but not of modifying `foreach'. Then the syntax should look like forevery( step; container; iterator) -manfred -manfred
Feb 25 2005
prev sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 24 Feb 2005 05:34:44 +0000 (UTC), James Dunne  
<jdunne4 bradley.edu> wrote:
 In article <opsmooadap23k2f5 ally>, Regan Heath says...
 On Thu, 24 Feb 2005 03:41:02 +0000 (UTC), James Dunne
 <jdunne4 bradley.edu> wrote:
 In article <opsmol1osx23k2f5 ally>, Regan Heath says...
 Does the term "foreach" imply any direction forward or backward? To me
 it
 doesn't. I realise it's used in other languages, the same as in D, so  
 it
 has a commonly understood meaning.

 I think the options are:

 - leave foreach, invent a backwards term i.e. foreach_r.
 - invent new terms, one for forward, one for backward.
 - add the ability to specify the 'step' in foreach


 Regan

I agree with the options listed, and really they're not up to me to decide ;). On specifying the 'step' for the foreach, that doesn't seem especially useful unless it's either +1 or -1, which I'm sure is what your point was.

Actually, I was being intentionally vague :)
 I'm just
 saying I don't see why anyone would use a container to foreach through
 on a
 specified interval bigger than one.

Isn't it the same reason someone would use a for loop with i+=2, or i-=2?

Not necessarily. Foreach was created to iterate through lists. for() was meant to give flexible looping ability. If you want to skip indicies, use a regular for() loop. Any well-implemented class that implements opApply (foreach support) should also implement opIndex to give access to individual elements.

I believe the other important goal was to make iteration through a container look identical, regardless of the container type. To save re-coding when changing container type, or writing generic code. If foreach can be modified to allow accessing every xth item of any container with the same syntax, regardless of type i.e. array, linklist, then I think this is the best solution. Given that opIndex for a linklist is inefficient, not having foreach do it, will mean people will use a for loop and be in the same situation as before foreach existed, recoding and having trouble writing generic code.
 Besides, adding a step, start, and end to the current foreach syntax has  
 the
 possibility of breaking code as it stands now.

I think breaking code pre 1.0 is ok, case by case, if we want to we'll have to consider it.
 However, they could be optional
 arguments and not break anything, or they could be an optionally allowed  
 syntax
 in addition to the "old (current) way".

This would be best if possible. Ben has come up with an idea I see.
 Of course in addition to the step you need some way to indicate where to
 start start, end, x.

 That is, unless you assume -1 means start at the end, and +1 means start
 at the beginning and that no-one ever wants to start elsewhere.

 I think the concept of direction and step can apply to arrays,  
 linklists,
 and other types of containers, if so does that mean foreach should  
 handle
 them?

If you can give me a legitimate example where you would *need* to skip elements on a constant step using foreach, then I'll agree with you. I just can't think of any off-hand.

Do you want a concrete example? or are the comments above about the goal of foreach and linklists sufficient?
 Maybe a punny syntax like "foreach" is short for forward-each

I thought it was "for each" as in "for each item in .."

That's technically what it means, yes. But I was just throwing in the pun of foreach breaking up as "forward" and "each" to allow a backeach meaning "back" and "each". Just a dumb pun, don't worry about it ;)

Ahh. Sorry, my sense of humour must have been on holiday.
 , and we could have
 "backeach".  foreach to me seems to imply order, and is usually
 implemented as a
 forward iteration.

I suspected that to others it might imply order.

And it does. When you foreach through a D array, you iterate forward through it. It's just generally accepted that it has a forward order to it. In other languages (e.g. PHP, Perl, C#) this is true as well.

Yep. Tho, I am one of those that doesn't have a problem being different, if I think different is better. Regan
Feb 24 2005
parent Georg Wrede <georg.wrede nospam.org> writes:
Regan Heath wrote:
 On Thu, 24 Feb 2005 05:34:44 +0000 (UTC), James Dunne  
 <jdunne4 bradley.edu> wrote:
 
 In article <opsmooadap23k2f5 ally>, Regan Heath says...

 On Thu, 24 Feb 2005 03:41:02 +0000 (UTC), James Dunne
 <jdunne4 bradley.edu> wrote:

 In article <opsmol1osx23k2f5 ally>, Regan Heath says...




 
 Besides, adding a step, start, and end to the current foreach syntax 
 has  the
 possibility of breaking code as it stands now.

I think breaking code pre 1.0 is ok, case by case, if we want to we'll have to consider it.

That is certainly true. Rather break as much as needed right now, than some later. Of course, any programmer who does even remotely "production" code does keep the precise version of compiler around. And for added security, zipped in the same file as his app sources! In a larger environment, of course the compiler versions are archeived anyway, so you only label the app as using V x.xx.0x.
Feb 27 2005
prev sibling next sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"James Dunne" <jdunne4 bradley.edu> wrote in message 
news:cvj34u$2b2s$1 digitaldaemon.com...
 I'd like to request an opApply-reverse operator and a new foreach-reverse
 construct (syntax up for discussion, don't flame me for my -reverse's).

 Possible syntax:  opApplyReverse and foreachreverse (or just foreachr)

 This would be especially useful for some lists you need to iterate through 
 in
 reverse.  You could have both the forward iterator and reverse iterator 
 versions
 in the same class.

 I came across this while coding with DFL.  I need to delete the selected 
 items
 from a ListBox control.  The ListBox offers a property called 
 selectedIndices(),
 and if you delete them in order, all the indices after the one you just 
 deleted
 become invalid (shifted up by one).  The correct way to do it would be to
 reverse iterate through the selectedIndices and delete them.  That way no
 indices would be invalid after you delete them.

 Anyone else think this would be a valuable addition to D?

 Regards,
 James Dunne

It would be nice to get something like it. I remember this coming when I was working on the containers in MinTL and so my solution there was to have a property called "backwards" on the container like List that returned a private struct that only implemented foreach (or something like that - I actually can't remember exactly without going and looking it up). So basically the user types List!(int) x; ... foreach(int item; x.backwards) { .... } to iterate backwards over a list. The "reverse" property of List works just like the array reverse property and reverses the list items in-place. I don't know if such a syntax would be a good idea in general. I suppose it depends on exactly how the type of x.backwards would work. Maybe it can have special behavior like "length" where it does magic things in different contexts (ironic that I'm saying this since I'm not a big fan of the magic length behavior).
Feb 23 2005
next sibling parent reply John Demme <me teqdruid.com> writes:
Ben Hinkle wrote:
   List!(int) x;
   ...
   foreach(int item; x.backwards) {
   ....
   }
 to iterate backwards over a list. The "reverse" property of List works just 
 like the array reverse property and reverses the list items in-place.

Sounds like you want the List template to have a backwards method that returns a class that will iterate over the original list backwards. Seems like a simple enough thing to do. Or do I misunderstand? John
Feb 23 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"John Demme" <me teqdruid.com> wrote in message 
news:cvj6rk$2e8n$1 digitaldaemon.com...
 Ben Hinkle wrote:
   List!(int) x;
   ...
   foreach(int item; x.backwards) {
   ....
   }
 to iterate backwards over a list. The "reverse" property of List works 
 just like the array reverse property and reverses the list items 
 in-place.

Sounds like you want the List template to have a backwards method that returns a class that will iterate over the original list backwards. Seems like a simple enough thing to do. Or do I misunderstand? John

Yeah - that's what I did. I was describing how I implemented a similar feature for non-arrays as another data point in the discussion.
Feb 23 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 23 Feb 2005 19:53:27 -0500, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 "John Demme" <me teqdruid.com> wrote in message
 news:cvj6rk$2e8n$1 digitaldaemon.com...
 Ben Hinkle wrote:
   List!(int) x;
   ...
   foreach(int item; x.backwards) {
   ....
   }
 to iterate backwards over a list. The "reverse" property of List works
 just like the array reverse property and reverses the list items
 in-place.

Sounds like you want the List template to have a backwards method that returns a class that will iterate over the original list backwards. Seems like a simple enough thing to do. Or do I misunderstand? John

Yeah - that's what I did. I was describing how I implemented a similar feature for non-arrays as another data point in the discussion.

It seems to me that it doesn't necessarily need to be a different class, it could be another copy of the same class, containing the same info, backwards. Of course, sometimes a different class is preferrable. Regan
Feb 23 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message 
news:opsmof4pem23k2f5 ally...
 On Wed, 23 Feb 2005 19:53:27 -0500, Ben Hinkle <ben.hinkle gmail.com> 
 wrote:
 "John Demme" <me teqdruid.com> wrote in message
 news:cvj6rk$2e8n$1 digitaldaemon.com...
 Ben Hinkle wrote:
   List!(int) x;
   ...
   foreach(int item; x.backwards) {
   ....
   }
 to iterate backwards over a list. The "reverse" property of List works
 just like the array reverse property and reverses the list items
 in-place.

Sounds like you want the List template to have a backwards method that returns a class that will iterate over the original list backwards. Seems like a simple enough thing to do. Or do I misunderstand? John

Yeah - that's what I did. I was describing how I implemented a similar feature for non-arrays as another data point in the discussion.

It seems to me that it doesn't necessarily need to be a different class, it could be another copy of the same class, containing the same info, backwards. Of course, sometimes a different class is preferrable. Regan

Two points: 1) it's actually a struct so that no garbage is created by foreaching backwards. If I had to choose between writing a for loop that steps backwards and writing a foreach loop that generating garbage I'd choose writing the for loop - but that's me. 2) a different type is needed because foreach on a regular List means forwards foreach and I decided that storing a flag as part of a general List just for backwards traversals wasn't worth the storage space. The actual implementation factors out the for loop into a function that the regular List calls with a step of +1 and the BackwardsList (or whatever name I used) calls with step -1.
Feb 23 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 23 Feb 2005 21:02:15 -0500, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsmof4pem23k2f5 ally...
 On Wed, 23 Feb 2005 19:53:27 -0500, Ben Hinkle <ben.hinkle gmail.com>
 wrote:
 "John Demme" <me teqdruid.com> wrote in message
 news:cvj6rk$2e8n$1 digitaldaemon.com...
 Ben Hinkle wrote:
   List!(int) x;
   ...
   foreach(int item; x.backwards) {
   ....
   }
 to iterate backwards over a list. The "reverse" property of List  
 works
 just like the array reverse property and reverses the list items
 in-place.

Sounds like you want the List template to have a backwards method that returns a class that will iterate over the original list backwards. Seems like a simple enough thing to do. Or do I misunderstand? John

Yeah - that's what I did. I was describing how I implemented a similar feature for non-arrays as another data point in the discussion.

It seems to me that it doesn't necessarily need to be a different class, it could be another copy of the same class, containing the same info, backwards. Of course, sometimes a different class is preferrable. Regan

Two points: 1) it's actually a struct so that no garbage is created by foreaching backwards. If I had to choose between writing a for loop that steps backwards and writing a foreach loop that generating garbage I'd choose writing the for loop - but that's me.

Yeah, this is what I was thinking about when I said that a different class (I meant to include struct) was preferrable sometimes.
 2) a different type is needed because foreach on a regular List means
 forwards foreach and I decided that storing a flag as part of a general  
 List just for backwards traversals wasn't worth the storage space.

You're probably right. Unless you were doing a lot of list reversals the common case would never need/use it. I was thinking that the simplest solution is to go: class List { List backwards() { List l = new List(); foreach(Item i; this) { l.addStart(i); } return l; } } in other words, make a new list, put the items in it in reverse order, return that. But, as you say, more garbage, less efficient.
 The actual implementation factors out the for loop into a function that  
 the regular List calls with a step of +1 and the BackwardsList (or  
 whatever name I used) calls with step -1.

Cunning, I'll have to have a look at that code at some stage. Regan
Feb 23 2005
parent reply "Andy" <andy.knowles gmail.com> writes:
Wouldn't this serve for now at least?  Personally I think it is better than
adding new keywords/operators to the language...  

<code>
module andy.backwards.backwards;

import std.stdio;

template backwards(List, Delegate)
{
struct reverse_iterator
{
List list;

int opApply(Delegate dg)
{
return list.opApplyReverse(dg);
}
}

reverse_iterator backwards()
{
reverse_iterator r;
r.list = this;
return r;
}
}

class Foo
{
mixin backwards!(Foo, int delegate(inout int));

int opApply(int delegate(inout int) dg)
{
int result = 0;
for(int i = 0; i < 10; i++)
{
result = dg(i);
if(result)
break;
}
return result;
}

int opApplyReverse(int delegate(inout int) dg)
{
int result = 0;
for(int i = 9; i >= 0; i--)
{
result = dg(i);
if(result)
break;
}
return result;
}
}

void main(char[][] args)
{
Foo foo = new Foo();

foreach(int i; foo)
writefln(i);

foreach(int i; foo.backwards)
writefln(i);
}
</code>

Adding a reverse iterator to a class requires only a mixin and the definition of
the iterator itself (called opApplyReverse here).  Calling the iterator requires
only a .backwards on the end of the foreach expression.

You can replace the templated delegate type with a templated item type to make
typing the mixins easier, but then you can't create different iterators (say
with an accompanying index).

Hopefully with inlining and optomising this would be about as fast as normal
foreaching?

In article <opsmojp1qc23k2f5 ally>, Regan Heath says...
On Wed, 23 Feb 2005 21:02:15 -0500, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsmof4pem23k2f5 ally...
 On Wed, 23 Feb 2005 19:53:27 -0500, Ben Hinkle <ben.hinkle gmail.com>
 wrote:
 "John Demme" <me teqdruid.com> wrote in message
 news:cvj6rk$2e8n$1 digitaldaemon.com...
 Ben Hinkle wrote:
   List!(int) x;
   ...
   foreach(int item; x.backwards) {
   ....
   }
 to iterate backwards over a list. The "reverse" property of List  
 works
 just like the array reverse property and reverses the list items
 in-place.

Sounds like you want the List template to have a backwards method that returns a class that will iterate over the original list backwards. Seems like a simple enough thing to do. Or do I misunderstand? John

Yeah - that's what I did. I was describing how I implemented a similar feature for non-arrays as another data point in the discussion.

It seems to me that it doesn't necessarily need to be a different class, it could be another copy of the same class, containing the same info, backwards. Of course, sometimes a different class is preferrable. Regan

Two points: 1) it's actually a struct so that no garbage is created by foreaching backwards. If I had to choose between writing a for loop that steps backwards and writing a foreach loop that generating garbage I'd choose writing the for loop - but that's me.

Yeah, this is what I was thinking about when I said that a different class (I meant to include struct) was preferrable sometimes.
 2) a different type is needed because foreach on a regular List means
 forwards foreach and I decided that storing a flag as part of a general  
 List just for backwards traversals wasn't worth the storage space.

You're probably right. Unless you were doing a lot of list reversals the common case would never need/use it. I was thinking that the simplest solution is to go: class List { List backwards() { List l = new List(); foreach(Item i; this) { l.addStart(i); } return l; } } in other words, make a new list, put the items in it in reverse order, return that. But, as you say, more garbage, less efficient.
 The actual implementation factors out the for loop into a function that  
 the regular List calls with a step of +1 and the BackwardsList (or  
 whatever name I used) calls with step -1.

Cunning, I'll have to have a look at that code at some stage. Regan

Feb 23 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Andy" <andy.knowles gmail.com> wrote in message 
news:cvjr4s$2kj$1 digitaldaemon.com...
 Wouldn't this serve for now at least?  Personally I think it is better 
 than
 adding new keywords/operators to the language...

 <code>
 module andy.backwards.backwards;

 import std.stdio;

 template backwards(List, Delegate)
 {
 struct reverse_iterator
 {
 List list;

 int opApply(Delegate dg)
 {
 return list.opApplyReverse(dg);
 }
 }

 reverse_iterator backwards()
 {
 reverse_iterator r;
 r.list = this;
 return r;
 }
 }

 class Foo
 {
 mixin backwards!(Foo, int delegate(inout int));

 int opApply(int delegate(inout int) dg)
 {
 int result = 0;
 for(int i = 0; i < 10; i++)
 {
 result = dg(i);
 if(result)
 break;
 }
 return result;
 }

 int opApplyReverse(int delegate(inout int) dg)
 {
 int result = 0;
 for(int i = 9; i >= 0; i--)
 {
 result = dg(i);
 if(result)
 break;
 }
 return result;
 }
 }

 void main(char[][] args)
 {
 Foo foo = new Foo();

 foreach(int i; foo)
 writefln(i);

 foreach(int i; foo.backwards)
 writefln(i);
 }
 </code>

 Adding a reverse iterator to a class requires only a mixin and the 
 definition of
 the iterator itself (called opApplyReverse here).  Calling the iterator 
 requires
 only a .backwards on the end of the foreach expression.

 You can replace the templated delegate type with a templated item type to 
 make
 typing the mixins easier, but then you can't create different iterators 
 (say
 with an accompanying index).

 Hopefully with inlining and optomising this would be about as fast as 
 normal
 foreaching?

That's one way. Here's what I did in MinTL for backwards iteration over arrays. Actually the code in MinTL also can produce a "sequence" (which is a run-time list of items) from an array but I removed that part since it doesn't matter here. One decision I remember wondering about was the count in foreach statements - should it just count 0 to n-1 or should it count n-1 to 0? The code I have here counts 0 to n-1 but I'm thinking now maybe it should count n-1 to 0. /** Iterate backwards over a dynamic array. This function should be * used on the target array in a foreach statement * \param x the array to iterate over. */ template backwards(Value : Value[]) { DArrayReverseIter!(Value) backwards(Value[] x) { DArrayReverseIter!(Value) y; y.x = x; return y; } } /* Private helper for reverse iteration */ private struct DArrayReverseIter(Value) { Value[] x; int opApply(int delegate(inout Value val) dg) { int res = 0; for (int n=x.length; n > 0; ) { res = dg(x[--n]); if (res) break; } return res; } int opApply(int delegate(inout int n, inout Value val) dg) { int res = 0; int cnt = 0; for (int n=x.length; n > 0; cnt++) { res = dg(cnt,x[--n]); if (res) break; } return res; } } import std.stdio; int main() { int[] t1, t2; t1.length = 4; t2.length = 4; for(int k=0;k<4;k++) t1[k] = k*100; foreach(int n, int val; backwards!(int[])(t1)) { writefln("n=%d val=%d",n,val); t2[n] = val; } assert( t1.reverse == t2 ); return 0; }
Feb 24 2005
parent reply "Andy Knowles" <andy.knowles gmail.com> writes:
Perhaps a good all round extension to the foreach statement would be if it
took delegates to iterators as well.  Then the following would work:

import std.stdio;

class Foo
{
  int opApply(int delegate(inout int) dg)
  {
    //default iterator
    return forwards(dg);
  }

  int forwards(int delegate(inout int) dg)
  {
    int result = 0;
    for(int i = 0; i < 10; i++)
    {
      result = dg(i);
      if(result)
        break;
    }
    return result;
  }

  int backwards(int delegate(inout int) dg)
  {
    int result = 0;
    for(int i = 9; i >= 0; i--)
    {
      result = dg(i);
      if(result)
        break;
    }
    return result;
  }
}

void main(char[][] args)
{
  Foo foo = new Foo();

  //implicit call to foo.opApply
  foreach(int i; foo)
    writefln(i);

  //explicit call to foo.opApply
  foreach(int i; &foo.opApply)
    writefln(i);

  //explicitly use forward iterator
  foreach(int i; &foo.forwards)
    writefln(i);

  //explicitly use reverse iterator
  foreach(int i; &foo.backwards)
    writefln(i);
}

The full type of the delegate would be int delegate(int delegate(inout
_type_ [, ...])).  I had a quick glance at the foreach conversion code in
statement.c, this change should be pretty simple.

This way you can have several named iterators on any class available for
easy usage, say for different tree traversals.  You could pass around
iterators as delegates, allowing you to write code that operates on an
entire collection while being completely independant of the type of the
collection itself.  If you really didn't like having the amperstand, you
could write a public property to return a private delegate.  And best of
all, the only thing you have changed is the type of expression a foreach
accepts.  No new syntax, statements, operators, or types of expressions.

Sound good?

"Ben Hinkle" <ben.hinkle gmail.com> wrote in message
news:cvkjv1$110l$1 digitaldaemon.com...
 "Andy" <andy.knowles gmail.com> wrote in message
 news:cvjr4s$2kj$1 digitaldaemon.com...
 Wouldn't this serve for now at least?  Personally I think it is better
 than
 adding new keywords/operators to the language...

 <code>
 module andy.backwards.backwards;

 import std.stdio;

 template backwards(List, Delegate)
 {
 struct reverse_iterator
 {
 List list;

 int opApply(Delegate dg)
 {
 return list.opApplyReverse(dg);
 }
 }

 reverse_iterator backwards()
 {
 reverse_iterator r;
 r.list = this;
 return r;
 }
 }

 class Foo
 {
 mixin backwards!(Foo, int delegate(inout int));

 int opApply(int delegate(inout int) dg)
 {
 int result = 0;
 for(int i = 0; i < 10; i++)
 {
 result = dg(i);
 if(result)
 break;
 }
 return result;
 }

 int opApplyReverse(int delegate(inout int) dg)
 {
 int result = 0;
 for(int i = 9; i >= 0; i--)
 {
 result = dg(i);
 if(result)
 break;
 }
 return result;
 }
 }

 void main(char[][] args)
 {
 Foo foo = new Foo();

 foreach(int i; foo)
 writefln(i);

 foreach(int i; foo.backwards)
 writefln(i);
 }
 </code>

 Adding a reverse iterator to a class requires only a mixin and the
 definition of
 the iterator itself (called opApplyReverse here).  Calling the iterator
 requires
 only a .backwards on the end of the foreach expression.

 You can replace the templated delegate type with a templated item type


 make
 typing the mixins easier, but then you can't create different iterators
 (say
 with an accompanying index).

 Hopefully with inlining and optomising this would be about as fast as
 normal
 foreaching?

That's one way. Here's what I did in MinTL for backwards iteration over arrays. Actually the code in MinTL also can produce a "sequence" (which is

 run-time list of items) from an array but I removed that part since it
 doesn't matter here. One decision I remember wondering about was the count
 in foreach statements - should it just count 0 to n-1 or should it count

 to 0? The code I have here counts 0 to n-1 but I'm thinking now maybe it
 should count n-1 to 0.

 /** Iterate backwards over a dynamic array. This function should be
  *  used on the target array in a foreach statement
  *  \param x the array to iterate over.
  */
 template backwards(Value : Value[]) {
   DArrayReverseIter!(Value) backwards(Value[] x) {
     DArrayReverseIter!(Value) y;
     y.x = x;
     return y;
   }
 }
 /* Private helper for reverse iteration */
 private struct DArrayReverseIter(Value) {
   Value[] x;
   int opApply(int delegate(inout Value val) dg) {
     int res = 0;
     for (int n=x.length; n > 0; ) {
       res = dg(x[--n]);
       if (res) break;
     }
     return res;
   }
   int opApply(int delegate(inout int n, inout Value val) dg) {
     int res = 0;
     int cnt = 0;
     for (int n=x.length; n > 0; cnt++) {
       res = dg(cnt,x[--n]);
       if (res) break;
     }
     return res;
   }
 }

 import std.stdio;
 int main() {
     int[] t1, t2;
     t1.length = 4;
     t2.length = 4;
     for(int k=0;k<4;k++) t1[k] = k*100;
     foreach(int n, int val; backwards!(int[])(t1)) {
       writefln("n=%d val=%d",n,val);
       t2[n] = val;
     }
     assert( t1.reverse == t2 );
     return 0;
 }

Feb 24 2005
parent "Ben Hinkle" <bhinkle mathworks.com> writes:
"Andy Knowles" <andy.knowles gmail.com> wrote in message 
news:cvm7hp$2lr4$1 digitaldaemon.com...
 Perhaps a good all round extension to the foreach statement would be if it
 took delegates to iterators as well.

That is a pretty neat idea. It got me thinking. A post of Manfred's on this thread mentioned breadth-first and depth-first traversals and it would be nice to be able to specify which kind of traversal you want in a foreach (if the tree supplied those). Using your propsed syntax, foreach(int i; &foo.breadthFirst) writefln(i); foreach(int i, &foo.depthFirst) writefln(i); (plus most likely the reverse versions of breadth and depth first). Yet another way to skin this cat is to allow trailing parameters to foreach. For example class Foo { int opApply(int delegate(inout int) dg, bool reverse = false) { ... } } that can be used like foreach(int x; obj) { ... } % called with reverse = false or foreach(int x; obj; true) { ... }% called with reverse = true Or users can pass a step parameter if allowed: class Foo { int opApply(int delegate(inout int) dg, int step = 1) { ... } } foreach(int x; obj; 2) { ... }% called with step = 2 Or users can pass a flag for tree traversals: const int BreathFirst = 0; const int DepthFirst = 1; class Tree { int opApply(int delegate(inout int) dg, int method = BreadthFirst) { ... } } foreach(int x; obj) { ... }% called with method = BreadthFirst foreach(int x; obj; DepthFirst) { ... }% called with method = DepthFirst Anyhow, I hope foreach gets something like any of these ideas- it would be pretty useful to customize traversals. -Ben
Feb 25 2005
prev sibling parent reply James Dunne <jdunne4 bradley.edu> writes:
In article <cvj669$2dtp$1 digitaldaemon.com>, Ben Hinkle says...
It would be nice to get something like it. I remember this coming when I was 
working on the containers in MinTL and so my solution there was to have a 
property called "backwards" on the container like List that returned a 
private struct that only implemented foreach (or something like that - I 
actually can't remember exactly without going and looking it up). So 
basically the user types
  List!(int) x;
  ...
  foreach(int item; x.backwards) {
  ....
  }
to iterate backwards over a list. The "reverse" property of List works just 
like the array reverse property and reverses the list items in-place.

You were clear up to this point... You lost me on this next paragraph.
I don't know if such a syntax would be a good idea in general. I suppose it 
depends on exactly how the type of x.backwards would work. Maybe it can have 
special behavior like "length" where it does magic things in different 
contexts (ironic that I'm saying this since I'm not a big fan of the magic 
length behavior). 

I'm proposing a new set of opApply and foreach constructs to simply provide support for reverse iteration. No special hacks need be introduced. Keep it simple and sweet. Regards, James Dunne
Feb 23 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
I don't know if such a syntax would be a good idea in general. I suppose 
it
depends on exactly how the type of x.backwards would work. Maybe it can 
have
special behavior like "length" where it does magic things in different
contexts (ironic that I'm saying this since I'm not a big fan of the magic
length behavior).

I'm proposing a new set of opApply and foreach constructs to simply provide support for reverse iteration. No special hacks need be introduced. Keep it simple and sweet.

Yeah that might be best. I don't have a strong opinion about what the best answer would be. I was exploring a solution that didn't involve adding a keyword. A reverse foreach over associative arrays isn't needed because the order is random anyway so should AA's be foreachreverse-able? Maybe there's some solution involving adding a stepsize argument to the foreach and saying that negative step sizes are reverse traversals? eh, I don't know.
Feb 23 2005
parent reply James Dunne <jdunne4 bradley.edu> writes:
In article <cvjgro$2odu$1 digitaldaemon.com>, Ben Hinkle says...
I don't know if such a syntax would be a good idea in general. I suppose 
it
depends on exactly how the type of x.backwards would work. Maybe it can 
have
special behavior like "length" where it does magic things in different
contexts (ironic that I'm saying this since I'm not a big fan of the magic
length behavior).

I'm proposing a new set of opApply and foreach constructs to simply provide support for reverse iteration. No special hacks need be introduced. Keep it simple and sweet.

Yeah that might be best. I don't have a strong opinion about what the best answer would be. I was exploring a solution that didn't involve adding a keyword. A reverse foreach over associative arrays isn't needed because the order is random anyway so should AA's be foreachreverse-able? Maybe there's some solution involving adding a stepsize argument to the foreach and saying that negative step sizes are reverse traversals? eh, I don't know.

I understand what you were doing with MinTL and the .backwards property. I'd like to try to accomplish it without any memory duplication or "garbage produced." If that involves adding a new keyword to the language, that's fine with me! You can't foreach on an AA by itself, you have to foreach on the .keys or the values properties of the AA, which are just regular arrays. So if the foreach-reverse keyword is introduced, you'd reverse iterate on the keys or the values of the AA. Of course, reverse iteration on the keys or values doesn't matter much, unless you want to reverse iterate through the SORTED keys or values, which DOES make sense. :) Regards, James Dunne
Feb 23 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 You can't foreach on an AA by itself, you have to foreach on the .keys or 
 the
 values properties of the AA, which are just regular arrays.

yes, you can. for example: import std.stdio; int main() { int[int] x; x[100]=1; x[-100]=2; x[10]=3; foreach(int key, int val; x) { writefln("key %d val %d",key,val); } return 0; }
 So if the foreach-reverse keyword is introduced, you'd reverse iterate on 
 the
 keys or the values of the AA.

 Of course, reverse iteration on the keys or values doesn't matter much, 
 unless
 you want to reverse iterate through the SORTED keys or values, which DOES 
 make
 sense. :)

 Regards,
 James Dunne 

Feb 24 2005
parent reply James Dunne <jdunne4 bradley.edu> writes:
In article <cvkk7t$1194$1 digitaldaemon.com>, Ben Hinkle says...
 You can't foreach on an AA by itself, you have to foreach on the .keys or 
 the
 values properties of the AA, which are just regular arrays.

yes, you can. for example: import std.stdio; int main() { int[int] x; x[100]=1; x[-100]=2; x[10]=3; foreach(int key, int val; x) { writefln("key %d val %d",key,val); } return 0; }

That's a new one to me! It's not explained in the documentation, so I didn't think it existed. Looks like I have to do some research on the foreach allowable syntax to see what it's really capable of. This could just boil down to a simple documentation problem (or lack thereof). Regards, James Dunne
Feb 24 2005
next sibling parent "Regan Heath" <regan netwin.co.nz> writes:
On Fri, 25 Feb 2005 00:58:20 +0000 (UTC), James Dunne  
<jdunne4 bradley.edu> wrote:
 In article <cvkk7t$1194$1 digitaldaemon.com>, Ben Hinkle says...
 You can't foreach on an AA by itself, you have to foreach on the .keys  
 or
 the
 values properties of the AA, which are just regular arrays.

yes, you can. for example: import std.stdio; int main() { int[int] x; x[100]=1; x[-100]=2; x[10]=3; foreach(int key, int val; x) { writefln("key %d val %d",key,val); } return 0; }

That's a new one to me! It's not explained in the documentation, so I didn't think it existed. Looks like I have to do some research on the foreach allowable syntax to see what it's really capable of. This could just boil down to a simple documentation problem (or lack thereof).

IIRC the above doesn't give you 'sorted' information, so it's only really good if you don't care about what order it comes out in. Regan
Feb 24 2005
prev sibling parent "Ben Hinkle" <bhinkle mathworks.com> writes:
"James Dunne" <jdunne4 bradley.edu> wrote in message 
news:cvlt7c$2csq$1 digitaldaemon.com...
 In article <cvkk7t$1194$1 digitaldaemon.com>, Ben Hinkle says...
 You can't foreach on an AA by itself, you have to foreach on the .keys 
 or
 the
 values properties of the AA, which are just regular arrays.

yes, you can. for example: import std.stdio; int main() { int[int] x; x[100]=1; x[-100]=2; x[10]=3; foreach(int key, int val; x) { writefln("key %d val %d",key,val); } return 0; }

That's a new one to me! It's not explained in the documentation, so I didn't think it existed. Looks like I have to do some research on the foreach allowable syntax to see what it's really capable of. This could just boil down to a simple documentation problem (or lack thereof). Regards, James Dunne

It would be nice to have more links between related sections of the doc. The stuff about assoc arrays and foreach is under the "foreach" help. See http://www.digitalmars.com/d/statement.html#foreach the paragraph starting with "If the aggregate expression is an associative array"
Feb 25 2005
prev sibling parent Georg Wrede <georg.wrede nospam.org> writes:
James Dunne wrote:
 I'd like to request an opApply-reverse operator and a new foreach-reverse
 construct (syntax up for discussion, don't flame me for my -reverse's).
 
 Possible syntax:  opApplyReverse and foreachreverse (or just foreachr)
 
 This would be especially useful for some lists you need to iterate through in
 reverse.  You could have both the forward iterator and reverse iterator
versions
 in the same class.
 
 I came across this while coding with DFL.  I need to delete the selected items
 from a ListBox control.  The ListBox offers a property called
selectedIndices(),
 and if you delete them in order, all the indices after the one you just deleted
 become invalid (shifted up by one).  The correct way to do it would be to
 reverse iterate through the selectedIndices and delete them.  That way no
 indices would be invalid after you delete them.
 
 Anyone else think this would be a valuable addition to D?
 
 Regards,
 James Dunne

Norbert & Co, should we have: foreach (i in m..n) // itreate in no particular order a[i] = b[i] + 3 * c[i]; in addition to the (quite cool) "existing" vectorising syntax? (and of course, to avoid hierarchy:) foreach (i in a..b, j in c..d, k in e..f) a[i,j,k] = foo_op(x,y,z[j+i+k-2]); // or whatever
Feb 23 2005