Jump to page: 1 2 3
Thread overview
Foreach Range Statement
Jul 22, 2007
Xinok
Jul 23, 2007
Bill Baxter
Jul 23, 2007
Reiner Pope
Jul 23, 2007
Don Clugston
Jul 23, 2007
Bill Baxter
Jul 23, 2007
Reiner Pope
Jul 23, 2007
Oskar Linde
Jul 23, 2007
Sean Kelly
Jul 23, 2007
Bill Baxter
Jul 23, 2007
Don Clugston
Jul 23, 2007
Sean Kelly
Jul 23, 2007
Don Clugston
Jul 23, 2007
Sean Kelly
Jul 23, 2007
Bill Baxter
Jul 24, 2007
Don Clugston
Jul 24, 2007
Bill Baxter
Jul 23, 2007
Bill Baxter
Jul 23, 2007
Reiner Pope
Jul 23, 2007
renoX
Jul 23, 2007
Reiner Pope
Jul 23, 2007
Bill Baxter
July 22, 2007
I'd like to suggest my own design for this. I originally posted it to the unofficial wish list to see how many votes it would get:
http://all-technology.com/eigenpolls/dwishlist/index.php?it=142

The arguments are basically the same as the range / xrange functions in Python.

The only thing my design doesn't provide is foreach_reverse. Python automatically reverses provided the values are correct (xrange(10, 0, -1)), but this would cause a small overhead in the loop.


for i(100)
foreach(i; 0..100)
for(int i = 0; i < 100; ++i)

for i(100, 200)
foreach(i; 100..200)
for(int i = 100; i < 200; ++i)

for i(200, 400, 2)
-- Not possible using foreach
for(int i = 200; i < 400; i += 2)
July 23, 2007
"Xinok" <xnknet@gmail.com> wrote in message news:f80qof$2n0l$1@digitalmars.com...

> foreach(i; 0..100)

This is almost identical to the syntax in MiniD:

for(i: 0 .. 100)

It could be done with for or foreach; I just chose for because normally you use for loops to iterate over ranges of integers.

You can also come up with a pretty simple short-term solution that'll be fairly efficient (though not as efficient as if the compiler were aware of this kind of loop intrinsically) by making a struct 'range' which has a static opCall to construct a range and an opApply to iterate over the values, so that it'd look like:

foreach(i; range(100))

Which isn't terrible at all.


July 23, 2007
"Jarrett Billingsley" <kb3ctd2@yahoo.com> wrote in message news:f816re$96v$1@digitalmars.com...

I should really check .announce before posting things here XD


July 23, 2007
Jarrett Billingsley wrote:
> "Xinok" <xnknet@gmail.com> wrote in message news:f80qof$2n0l$1@digitalmars.com...
> 
>> foreach(i; 0..100)
> 
> This is almost identical to the syntax in MiniD:
> 
> for(i: 0 .. 100)
> 
> It could be done with for or foreach; I just chose for because normally you use for loops to iterate over ranges of integers.
> 
> You can also come up with a pretty simple short-term solution that'll be fairly efficient (though not as efficient as if the compiler were aware of this kind of loop intrinsically) by making a struct 'range' which has a static opCall to construct a range and an opApply to iterate over the values, so that it'd look like:
> 
> foreach(i; range(100))
> 
> Which isn't terrible at all. 

And it has the advantage of being more extensible.  And for allowing ranges to be treated as first class entities that can be passed around and manipulated.  But no, instead we get another one-trick pony.

--bb
July 23, 2007
Bill Baxter wrote:
> Jarrett Billingsley wrote:
>> "Xinok" <xnknet@gmail.com> wrote in message news:f80qof$2n0l$1@digitalmars.com...
>>
>>> foreach(i; 0..100)
>>
>> This is almost identical to the syntax in MiniD:
>>
>> for(i: 0 .. 100)
>>
>> It could be done with for or foreach; I just chose for because normally you use for loops to iterate over ranges of integers.
>>
>> You can also come up with a pretty simple short-term solution that'll be fairly efficient (though not as efficient as if the compiler were aware of this kind of loop intrinsically) by making a struct 'range' which has a static opCall to construct a range and an opApply to iterate over the values, so that it'd look like:
>>
>> foreach(i; range(100))
>>
>> Which isn't terrible at all. 
> 
> And it has the advantage of being more extensible.  And for allowing ranges to be treated as first class entities that can be passed around and manipulated.  But no, instead we get another one-trick pony.
> 
> --bb
That was my first thought, too.

In the "Array Slice Ranges" thread, several people mentioned first-class ranges:

http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43865
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43904
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43905
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43954

Your implementation, Bill, seems to be just right, and gives you foreach over ranges for free.

What's wrong with adding that to the language, but templated and with nice syntax?

type name                                 literal
int..int  (range of int)                  1..5
int..double   (range of int to double)    1..5.0
int..int:int  (stepped range)             5..1:-1

(I'm not sure of the use of mixed-type ranges, but this seems the most intuitive syntax. Since most ranges are probably of one type, how about allowing a symbol to denote "same type again". Any of the following could mean int..int:   int..#,   int.._, int..$)

As several people have pointed out, this also fixes mixed indexing/slicing problems for multi-dimensional arrays.



  Reiner
July 23, 2007
Reiner Pope wrote:
> Bill Baxter wrote:
>> Jarrett Billingsley wrote:
>>> "Xinok" <xnknet@gmail.com> wrote in message news:f80qof$2n0l$1@digitalmars.com...
>>>
>>>> foreach(i; 0..100)
>>>
>>> This is almost identical to the syntax in MiniD:
>>>
>>> for(i: 0 .. 100)
>>>
>>> It could be done with for or foreach; I just chose for because normally you use for loops to iterate over ranges of integers.
>>>
>>> You can also come up with a pretty simple short-term solution that'll be fairly efficient (though not as efficient as if the compiler were aware of this kind of loop intrinsically) by making a struct 'range' which has a static opCall to construct a range and an opApply to iterate over the values, so that it'd look like:
>>>
>>> foreach(i; range(100))
>>>
>>> Which isn't terrible at all. 
>>
>> And it has the advantage of being more extensible.  And for allowing ranges to be treated as first class entities that can be passed around and manipulated.  But no, instead we get another one-trick pony.
>>
>> --bb
> That was my first thought, too.
> 
> In the "Array Slice Ranges" thread, several people mentioned first-class ranges:
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43865 
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43904 
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43905 
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43954 
> 
> 
> Your implementation, Bill, seems to be just right, and gives you foreach over ranges for free.
> 
> What's wrong with adding that to the language, but templated and with nice syntax?
> 
> type name                                 literal
> int..int  (range of int)                  1..5
> int..double   (range of int to double)    1..5.0
> int..int:int  (stepped range)             5..1:-1
> 
> (I'm not sure of the use of mixed-type ranges, but this seems the most intuitive syntax. Since most ranges are probably of one type, how about allowing a symbol to denote "same type again". Any of the following could mean int..int:   int..#,   int.._, int..$)

I don't think it make sense to have mixed type ranges. The normal promotion rules should apply. However...

Floating-point ranges are tricky. Should they be open-ended, or closed-ended? Consider
-real.infinity..real.infinity
Are the infinities part of the range? If not, how do you specify a range which includes infinity?

I think the convention "first_element .. last_element+1" cannot be extended to negative and floating-point numbers without creating an inconsistency. Which is quite unfortunate.


July 23, 2007
Reiner Pope wrote:
> Bill Baxter wrote:
>> Jarrett Billingsley wrote:
>>> "Xinok" <xnknet@gmail.com> wrote in message news:f80qof$2n0l$1@digitalmars.com...
>>>
>>>> foreach(i; 0..100)
>>>
>>> This is almost identical to the syntax in MiniD:
>>>
>>> for(i: 0 .. 100)
>>>
>>> It could be done with for or foreach; I just chose for because normally you use for loops to iterate over ranges of integers.
>>>
>>> You can also come up with a pretty simple short-term solution that'll be fairly efficient (though not as efficient as if the compiler were aware of this kind of loop intrinsically) by making a struct 'range' which has a static opCall to construct a range and an opApply to iterate over the values, so that it'd look like:
>>>
>>> foreach(i; range(100))
>>>
>>> Which isn't terrible at all. 
>>
>> And it has the advantage of being more extensible.  And for allowing ranges to be treated as first class entities that can be passed around and manipulated.  But no, instead we get another one-trick pony.
>>
>> --bb
> That was my first thought, too.
> 
> In the "Array Slice Ranges" thread, several people mentioned first-class ranges:
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43865 
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43904 
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43905 
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43954 
> 
> 
> Your implementation, Bill, seems to be just right, and gives you foreach over ranges for free.

Thanks.  I think Oskar Linde had a nice version too.  I seem to remember thinking there were a few things in his that I should borrow.

> What's wrong with adding that to the language, but templated and with nice syntax?
> 
> type name                                 literal
> int..int  (range of int)                  1..5
> int..double   (range of int to double)    1..5.0
> int..int:int  (stepped range)             5..1:-1
> 
> (I'm not sure of the use of mixed-type ranges, but this seems the most intuitive syntax. Since most ranges are probably of one type, how about allowing a symbol to denote "same type again". Any of the following could mean int..int:   int..#,   int.._, int..$)

Having two different types for it seems odd.  Just plain int.. would make more sense to me.  I really like that 5..1:-1 syntax though!  Was that mentioned before?  Something about all the colons in Pythons range literals always makes me uneasy.  a:b:c -- is that a to c stepping by b?  Or a to b stepping by c?  In Python it's the latter.  In Matlab I think it's the former.  Which is probably why I always feel a little uneasy when I see it.  But a..b:c is much clearer!  Obviously it's from a to b, so c must be a step.  And the colon looking like the two dots stood on end -- lovely.

> As several people have pointed out, this also fixes mixed indexing/slicing problems for multi-dimensional arrays.

To give Walter the benefit of the doubt, perhaps this new addition *is* the first stage of just such a master plan to make range literals first class citizens.


--bb
July 23, 2007
Reiner Pope wrote:
> Bill Baxter wrote:
>> Jarrett Billingsley wrote:
>>> "Xinok" <xnknet@gmail.com> wrote in message news:f80qof$2n0l$1@digitalmars.com...
>>>
>>>> foreach(i; 0..100)
>>>
>>> This is almost identical to the syntax in MiniD:
>>>
>>> for(i: 0 .. 100)
>>>
>>> It could be done with for or foreach; I just chose for because normally you use for loops to iterate over ranges of integers.
>>>
>>> You can also come up with a pretty simple short-term solution that'll be fairly efficient (though not as efficient as if the compiler were aware of this kind of loop intrinsically) by making a struct 'range' which has a static opCall to construct a range and an opApply to iterate over the values, so that it'd look like:
>>>
>>> foreach(i; range(100))
>>>
>>> Which isn't terrible at all. 
>>
>> And it has the advantage of being more extensible.  And for allowing ranges to be treated as first class entities that can be passed around and manipulated.  But no, instead we get another one-trick pony.
>>
>> --bb
> That was my first thought, too.
> 
> In the "Array Slice Ranges" thread, several people mentioned first-class ranges:
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43865 
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43904 
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43905 
> 
> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43954 
> 
> 
> Your implementation, Bill, seems to be just right, and gives you foreach over ranges for free.
> 
> What's wrong with adding that to the language, but templated and with nice syntax?
> 
> type name                                 literal
> int..int  (range of int)                  1..5
> int..double   (range of int to double)    1..5.0
> int..int:int  (stepped range)             5..1:-1
> 
> (I'm not sure of the use of mixed-type ranges, but this seems the most intuitive syntax. Since most ranges are probably of one type, how about allowing a symbol to denote "same type again". Any of the following could mean int..int:   int..#,   int.._, int..$)
> 
> As several people have pointed out, this also fixes mixed indexing/slicing problems for multi-dimensional arrays.
> 
> 
> 
>   Reiner
Oh, and let's throw in another dimension for good measure: :-)

Adding a '?' after the type means it's optional. This means two things: you can omit the value in literals, and it will be its default value; and it can be cast to from other range types, so 'int..int' can be implicitly converted to 'int..int:int?' but not 'int..int:int'. This gives a use for mixed-type ranges:

typedef size_t step = 1;

struct MyArray(T)
{
   ...
   // returns a slice of the array, with a step of 1 unless specified
   MyArray!(T) opIndex(size_t..size_t:step? range)
   {
       ...
   }
}


But with # *and* ? being used by slice syntax, it might be using a few too many symbols for one concept....

  Reiner
July 23, 2007
Don Clugston wrote:
> Reiner Pope wrote:
>> Bill Baxter wrote:
>>> Jarrett Billingsley wrote:
>>>> "Xinok" <xnknet@gmail.com> wrote in message news:f80qof$2n0l$1@digitalmars.com...
>>>>
>>>>> foreach(i; 0..100)
>>>>
>>>> This is almost identical to the syntax in MiniD:
>>>>
>>>> for(i: 0 .. 100)
>>>>
>>>> It could be done with for or foreach; I just chose for because normally you use for loops to iterate over ranges of integers.
>>>>
>>>> You can also come up with a pretty simple short-term solution that'll be fairly efficient (though not as efficient as if the compiler were aware of this kind of loop intrinsically) by making a struct 'range' which has a static opCall to construct a range and an opApply to iterate over the values, so that it'd look like:
>>>>
>>>> foreach(i; range(100))
>>>>
>>>> Which isn't terrible at all. 
>>>
>>> And it has the advantage of being more extensible.  And for allowing ranges to be treated as first class entities that can be passed around and manipulated.  But no, instead we get another one-trick pony.
>>>
>>> --bb
>> That was my first thought, too.
>>
>> In the "Array Slice Ranges" thread, several people mentioned first-class ranges:
>>
>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43865 
>>
>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43904 
>>
>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43905 
>>
>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43954 
>>
>>
>> Your implementation, Bill, seems to be just right, and gives you foreach over ranges for free.
>>
>> What's wrong with adding that to the language, but templated and with nice syntax?
>>
>> type name                                 literal
>> int..int  (range of int)                  1..5
>> int..double   (range of int to double)    1..5.0
>> int..int:int  (stepped range)             5..1:-1
>>
>> (I'm not sure of the use of mixed-type ranges, but this seems the most intuitive syntax. Since most ranges are probably of one type, how about allowing a symbol to denote "same type again". Any of the following could mean int..int:   int..#,   int.._, int..$)
> 
> I don't think it make sense to have mixed type ranges. The normal promotion rules should apply. However...
> 
> Floating-point ranges are tricky. Should they be open-ended, or closed-ended? 

Both Matlab and Numpy have floating point ranges.   Matlab ranges are always inclusive, so 1:2.1:7.3 gives you 1.0, 3.1, 5.2, 7.3.  Python ranges are always non-inclusive, so it gives you 1.0,3.1,5.2.

> Consider
> -real.infinity..real.infinity
> Are the infinities part of the range? If not, how do you specify a range which includes infinity?

Does it matter that much?  I suppose it would be cool if it did something really consistent, but Numpy just craps out and gives you an empty list, and Matlab raises an error "Maximum variable size allowed by the program is exceeded".

> I think the convention "first_element .. last_element+1" cannot be extended to negative and floating-point numbers without creating an inconsistency. Which is quite unfortunate.

In Python the last_element..first_element inclusive case is handled by omissions.
  10:0:-1  --- 10 downto 1, inclusive -- doesn't include 0
  10::-1 --- 10 downto last one - includes 0

For D I guess that might become
   10..$:-1
but $ would have to become something context sensitive, rather than just a synonym for .length.  Which I guess is the same as saying you'd have to introduce an inconsistency, or at least a less strict form of consistency, to the interpretation of $.

--bb
July 23, 2007
Reiner Pope wrote:
> Reiner Pope wrote:
>> Bill Baxter wrote:
>>> Jarrett Billingsley wrote:
>>>> "Xinok" <xnknet@gmail.com> wrote in message news:f80qof$2n0l$1@digitalmars.com...
>>>>
>>>>> foreach(i; 0..100)
>>>>
>>>> This is almost identical to the syntax in MiniD:
>>>>
>>>> for(i: 0 .. 100)
>>>>
>>>> It could be done with for or foreach; I just chose for because normally you use for loops to iterate over ranges of integers.
>>>>
>>>> You can also come up with a pretty simple short-term solution that'll be fairly efficient (though not as efficient as if the compiler were aware of this kind of loop intrinsically) by making a struct 'range' which has a static opCall to construct a range and an opApply to iterate over the values, so that it'd look like:
>>>>
>>>> foreach(i; range(100))
>>>>
>>>> Which isn't terrible at all. 
>>>
>>> And it has the advantage of being more extensible.  And for allowing ranges to be treated as first class entities that can be passed around and manipulated.  But no, instead we get another one-trick pony.
>>>
>>> --bb
>> That was my first thought, too.
>>
>> In the "Array Slice Ranges" thread, several people mentioned first-class ranges:
>>
>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43865 
>>
>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43904 
>>
>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43905 
>>
>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43954 
>>
>>
>> Your implementation, Bill, seems to be just right, and gives you foreach over ranges for free.
>>
>> What's wrong with adding that to the language, but templated and with nice syntax?
>>
>> type name                                 literal
>> int..int  (range of int)                  1..5
>> int..double   (range of int to double)    1..5.0
>> int..int:int  (stepped range)             5..1:-1
>>
>> (I'm not sure of the use of mixed-type ranges, but this seems the most intuitive syntax. Since most ranges are probably of one type, how about allowing a symbol to denote "same type again". Any of the following could mean int..int:   int..#,   int.._, int..$)
>>
>> As several people have pointed out, this also fixes mixed indexing/slicing problems for multi-dimensional arrays.
>>
>>
>>
>>   Reiner
> Oh, and let's throw in another dimension for good measure: :-)
> 
> Adding a '?' after the type means it's optional. This means two things: you can omit the value in literals, and it will be its default value; and it can be cast to from other range types, so 'int..int' can be implicitly converted to 'int..int:int?' but not 'int..int:int'. This gives a use for mixed-type ranges:
> 
> typedef size_t step = 1;
> 
> struct MyArray(T)
> {
>    ...
>    // returns a slice of the array, with a step of 1 unless specified
>    MyArray!(T) opIndex(size_t..size_t:step? range)
>    {
>        ...
>    }
> }
> 
> 
> But with # *and* ? being used by slice syntax, it might be using a few too many symbols for one concept....

Let's just call it __slice.  I think __traits is lonely.



--bb
« First   ‹ Prev
1 2 3