May 18, 2009
Andrei Alexandrescu wrote:
> Consider:
> 
>     foreach (x; 1.0 .. 4.1) writeln(x);
>     foreach_reverse (x; 1.0 .. 4.1) writeln(x);
> 
> This sucks. foreach with interval for floating-point types should be disallowed.
> 
> 
> Andrei

I didn't even know this was possible, but I agree, it's an ugly thing.

-Lars
May 18, 2009
On Mon, 18 May 2009 04:28:24 +0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Consider:
>
>      foreach (x; 1.0 .. 4.1) writeln(x);
>      foreach_reverse (x; 1.0 .. 4.1) writeln(x);
>
> This sucks. foreach with interval for floating-point types should be disallowed.
>
>
> Andrei

It's useless, unless a step is specified (btw, integer iteration would benefit from having a step, too)

I don't mind if the whole .. feature is removed. It could be implemented in a library, with an optional step:

foreach (x; range(0, 100)) { // step is 1 implicitly
   // ...
}

foreach (x; range(0, 100, 2)) { // explicit step
   // ...
}

This feels more functional, although slightly longer to type.

May 18, 2009
grauzone wrote:
> Look at this for example:
>  > writefln("%s", is(typeof(rtzx) == char));
> This compiles even if rtzx doesn't exist. But you probably wanted to check the type of rtzx, not it if rtzx exists. If you mistyped rtzx, the compiler will never tell you.

You can do 'is(typeof(rtzx)) && is(typeof(rtzx) == char)', or wrap it in a template.
May 18, 2009
Christopher Wright wrote:
> grauzone wrote:
>> Look at this for example:
>>  > writefln("%s", is(typeof(rtzx) == char));
>> This compiles even if rtzx doesn't exist. But you probably wanted to check the type of rtzx, not it if rtzx exists. If you mistyped rtzx, the compiler will never tell you.
> 
> You can do 'is(typeof(rtzx)) && is(typeof(rtzx) == char)', or wrap it in a template.

The first is() in your expression is completely redundant, though. Not sure what you mean.

Anyway, my point was not about what's possible, but that it leads to not very robust code. Besides, you can't even tell what exactly went wrong inside the is(), because the compiler (of course) doesn't emit any error messages if that code isn't compileable.
May 18, 2009
On Sun, 17 May 2009 20:28:24 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Consider:
>
>      foreach (x; 1.0 .. 4.1) writeln(x);
>      foreach_reverse (x; 1.0 .. 4.1) writeln(x);
>
> This sucks. foreach with interval for floating-point types should be disallowed.

foreach_reverse sucks in its own right, while you're looking for stuff to get rid of, I think it can be done better.

foreach(x; 4 .. 1 ) should do a reverse interval (and looks way more readable).
foreach(x; array.reverse) should iterate in reverse.

for classes, using a method called reverse should work fine:

foreach(x; myclass.reverse)

Having to implement opApplyReverse is rediculous, and having a keyword like foreach_reverse is rediculous.  Reverse isn't the only interesting iteration pattern, so why focus a whole keyword and syntax on that?

-Steve
May 18, 2009
Steven Schveighoffer wrote:
> On Sun, 17 May 2009 20:28:24 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> 
>> Consider:
>>
>>      foreach (x; 1.0 .. 4.1) writeln(x);
>>      foreach_reverse (x; 1.0 .. 4.1) writeln(x);
>>
>> This sucks. foreach with interval for floating-point types should be disallowed.
> 
> foreach_reverse sucks in its own right, while you're looking for stuff to get rid of, I think it can be done better.
> 
> foreach(x; 4 .. 1 ) should do a reverse interval (and looks way more readable).
> foreach(x; array.reverse) should iterate in reverse.
> 
> for classes, using a method called reverse should work fine:
> 
> foreach(x; myclass.reverse)
> 
> Having to implement opApplyReverse is rediculous, and having a keyword like foreach_reverse is rediculous.  Reverse isn't the only interesting iteration pattern, so why focus a whole keyword and syntax on that?
> 
> -Steve

I agree with that, but how would you differ foreach(x; array.reverse) from the array.reverse that modifies the array?
May 18, 2009
On Mon, 18 May 2009 09:54:16 -0400, Jacob Carlborg <doob@me.com> wrote:

> Steven Schveighoffer wrote:
>> On Sun, 17 May 2009 20:28:24 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> Consider:
>>>
>>>      foreach (x; 1.0 .. 4.1) writeln(x);
>>>      foreach_reverse (x; 1.0 .. 4.1) writeln(x);
>>>
>>> This sucks. foreach with interval for floating-point types should be disallowed.
>>  foreach_reverse sucks in its own right, while you're looking for stuff to get rid of, I think it can be done better.
>>  foreach(x; 4 .. 1 ) should do a reverse interval (and looks way more readable).
>> foreach(x; array.reverse) should iterate in reverse.
>>  for classes, using a method called reverse should work fine:
>>  foreach(x; myclass.reverse)
>>  Having to implement opApplyReverse is rediculous, and having a keyword like foreach_reverse is rediculous.  Reverse isn't the only interesting iteration pattern, so why focus a whole keyword and syntax on that?
>>  -Steve
>
> I agree with that, but how would you differ foreach(x; array.reverse) from the array.reverse that modifies the array?

D'oh! I picked the wrong property name.  Forgot about the existing reverse property!

Just to clarify, I am *not* advocating that the propery way to iterate an array in reverse is to first reverse the array!

So pick some other property name:

foreach(x; array.backwards)

or whatever.  Too bad reverse is already taken :(

-Steve
May 18, 2009
== Quote from Steven Schveighoffer (schveiguy@yahoo.com)'s article
> On Mon, 18 May 2009 09:54:16 -0400, Jacob Carlborg <doob@me.com> wrote:
> > Steven Schveighoffer wrote:
> >> On Sun, 17 May 2009 20:28:24 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> >>
> >>> Consider:
> >>>
> >>>      foreach (x; 1.0 .. 4.1) writeln(x);
> >>>      foreach_reverse (x; 1.0 .. 4.1) writeln(x);
> >>>
> >>> This sucks. foreach with interval for floating-point types should be disallowed.
> >>  foreach_reverse sucks in its own right, while you're looking for stuff
> >> to get rid of, I think it can be done better.
> >>  foreach(x; 4 .. 1 ) should do a reverse interval (and looks way more
> >> readable).
> >> foreach(x; array.reverse) should iterate in reverse.
> >>  for classes, using a method called reverse should work fine:
> >>  foreach(x; myclass.reverse)
> >>  Having to implement opApplyReverse is rediculous, and having a keyword
> >> like foreach_reverse is rediculous.  Reverse isn't the only interesting
> >> iteration pattern, so why focus a whole keyword and syntax on that?
> >>  -Steve
> >
> > I agree with that, but how would you differ foreach(x; array.reverse) from the array.reverse that modifies the array?
> D'oh! I picked the wrong property name.  Forgot about the existing reverse
> property!
> Just to clarify, I am *not* advocating that the propery way to iterate an
> array in reverse is to first reverse the array!
> So pick some other property name:
> foreach(x; array.backwards)
> or whatever.  Too bad reverse is already taken :(
> -Steve

I think what you're looking for is retro() in std.range.  There are a few problemswith getting rid of foreach_reverse, though:

1.  It would have to stay in D1.  This is not a serious problem, since D2 already introduces so many breaking changes.

2.  Using retro() would not be a full replacement when it comes to arrays.  For example, you can't get the indices by doing a

foreach(i, elem; retro(someArray)) {}

3.  As discussed here before, opApply has legitimate uses and is likely not going anywhere.  In this case, foreach_reverse is the only way to iterate over a range backwards.

4.  Iteration using the range interface is currently slower than with arrays.  I posted some benchmarks a while back that were meant to demonstrate something else but demonstrated this as a side effect.  This is unlikely to matter unless you're in a very small inner loop, such that the loop overhead is significant compared to the contents of the loop, but some people with insane performance requirements might care.
May 18, 2009
dsimcha, el 18 de mayo a las 14:58 me escribiste:
> 2.  Using retro() would not be a full replacement when it comes to arrays.  For example, you can't get the indices by doing a
> 
> foreach(i, elem; retro(someArray)) {}

Python has an "enumerate" function exactly for this. Is a generator that returns a tuple with (index, element). That should be easily implemented in D2 as a range, I guess.

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
May 18, 2009
On Mon, 18 May 2009 10:58:46 -0400, dsimcha <dsimcha@yahoo.com> wrote:

> I think what you're looking for is retro() in std.range.  There are a few
> problemswith getting rid of foreach_reverse, though:
>
> 1.  It would have to stay in D1.  This is not a serious problem, since D2 already
> introduces so many breaking changes.

Agreed, not a problem.

> 2.  Using retro() would not be a full replacement when it comes to arrays.  For
> example, you can't get the indices by doing a
>
> foreach(i, elem; retro(someArray)) {}

I'm talking about having a builtin property to arrays that signals it should be iterated in reverse, not a library solution.  It can enjoy the same benefits of the current foreach_reverse.

As a side note, we need to figure out how to make ranges so they can do things like get indices, there has been some discussion on that.  Not having indices is going to make interesting ranges hard to use.  For example, iterating over a dictionary using a range will have to return some kind of key/value pair.

> 3.  As discussed here before, opApply has legitimate uses and is likely not going
> anywhere.  In this case, foreach_reverse is the only way to iterate over a range
> backwards.

Not true.  You can call foreach(x; delegate) to iterate using any delegate that has the "opApply" form.  One minor restriction (that I proposed be removed, see issue 2443) is that it has to be a delegate, which means that you normally have to call it like this:

foreach(x; &obj.inReverse)

> 4.  Iteration using the range interface is currently slower than with arrays.  I
> posted some benchmarks a while back that were meant to demonstrate something else
> but demonstrated this as a side effect.  This is unlikely to matter unless you're
> in a very small inner loop, such that the loop overhead is significant compared to
> the contents of the loop, but some people with insane performance requirements
> might care.

Again, this is moot because I'm not proposing using library functions, they would be builtins (for arrays only of course, user objects still need to define an opApply-like function).

However, I think this will be fixed in the future, because range method calls should be inlined in the foreach loop (they are probably not currently).

And no feature should be discounted because it doesn't perform well today, unless you can prove that it's impossible to make it perform well.  I hate this mentality some people have about D.

Goes along with the mentality that modules should be small because the compiler/linker sucks at trimming unused portions from object files...

-Steve