www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 4112] New: Stride in foreach ranges

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4112

           Summary: Stride in foreach ranges
           Product: D
           Version: future
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: bearophile_hugs eml.cc



In D2 the range syntax of foreach is useful because it helps state the
iteration variable one time only instead of tree, it's cleaner and less
bug-prone than the normal for syntax, and it's useful in many situations
because many for loops are just over a numeric range (so the normal for syntax
can be left for more complex situations).

But beside natural series, for loops over arithmetic ranges too are common.
Currently in D2 this requires a normal for syntax:

for (int i = 0; i < 100; i += 2) {}

My experience with Python tells me that an optional stride can be useful here.
This is a possible syntax (the colon is useful to visually tell apart the third
value):

foreach (i; 0 .. 100 : 2) {}

(To keep things simpler, it can even be acceptable for the stride value to be a
value known at compile-time).

See also bug 4111.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 21 2010
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4112


Denis Derman <denis.spir gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |denis.spir gmail.com



---
I'm unsure whether this is a good thing. The issue is, for me, this feature
would only apply to numeric intervals (probably even only on integral ones).
While the notion of "by-step iteration" is completely general; I guess simply
orthogonal to sequence / iteration / range.
Thus, I would prefere a range factory like

    auto byStep (R) (int step) if (...)

typical use case:

    foreach (n ; iota(1..1000).byStep(3)) {...}

or better (see http://d.puremagic.com/issues/show_bug.cgi?id=5395)
    foreach (n ; (1..1000).byStep(3) {...}

What do you think?

Negative step meaning backwards? So that we get reverse for free... An issue
is, if this is not the case but negative step is intepreted literally, we get a
very weird semantics compared to apparent meaning.

Example for the simplest case of reverse iteration. Should iterating backwards
on 0..4 (meaning 3->2->1->0) be written (more direct):
    foreach (n ; (0..4).byStep(-1))
(translation in the case of indices:)
    foreach (i ; (0..a.length).byStep(-1))

or instead (more logical but imo completely unintuitive and difficult):
    foreach (n ; (3..-1).byStep(-1))
(translation in the case of indices:)
    foreach (i ; (a.length-1..-1).byStep(-1))

By the way, this issue applies to your proposal as well: what does 1..3:-2
Actually mean?
Finally, if ever we had a step syntax for i..j, I would prefere '/' than ':',
read as "by": 
    foreach (; i..j:k
--> traverse the interval i..j 'by' (steps of) k.


Denis

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 09 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4112




---
(Grrr! How can we edit our own posts? Could not find it.)

That was supposed to be:

Finally, if ever we had a step syntax for i..j, I would prefere '/' than ':',
read as "by": 
    foreach (n ; i..j/k)
--> traverse the interval i..j 'by' (steps of) k.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 09 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4112


Andrei Alexandrescu <andrei metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei metalanguage.com



06:11:30 PST ---

 (Grrr! How can we edit our own posts? Could not find it.)
 
 That was supposed to be:
 
 Finally, if ever we had a step syntax for i..j, I would prefere '/' than ':',
 read as "by": 
     foreach (n ; i..j/k)
 --> traverse the interval i..j 'by' (steps of) k.
That's traverse the interval i..j/k. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 09 2011
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4112





 or better (see http://d.puremagic.com/issues/show_bug.cgi?id=5395)
     foreach (n ; (1..1000).byStep(3) {...}
 
 What do you think?
Your syntax is too much wordy for something so common as this. There are too many parentheses too, that increase syntax noise and cause errors similar to your one, you have forgotten a closing ).
 By the way, this issue applies to your proposal as well: what does 1..3:-2
 Actually mean?
In Python it gives an empty range. The semantics of a negative stride is well founded in Python:
 range(1, 3, -2)
[]
 Finally, if ever we had a step syntax for i..j, I would prefere '/' than ':',
 read as "by": 
     foreach (; i..j:k
 --> traverse the interval i..j 'by' (steps of) k.
The / syntax means something different already: import std.stdio; void main() { int i = 10; int j = 100; int k = 5; foreach (x; i .. j / k) writeln(x); } ==> 10 11 12 13 14 15 16 17 18 19 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 09 2011