March 22, 2007

kris wrote:
> Daniel Keep wrote:
>>
>> kris wrote:
>>
>>> janderson wrote:
>>>
>>>> Andrei Alexandrescu (See Website For Email) wrote:
>>>>
>>>>>
>>>>> Yah :o). Speaking of foreach_reverse, probably it would be wise to
>>>>> lobby Walter to deprecate it in favor of foreach(reverse) (item ;
>>>>> collection) { ... }. The keyword(extra) syntax is definitely becoming
>>>>> a D signature syntax.
>>>>>
>>>>>
>>>>> Andrei
>>>>
>>>>
>>>> //Using your other suggestion:
>>>> foreach(reverse) (item ; collection) (item2 ; x->GetColection(b))
>>>> (item3 ; collection3)
>>>> {
>>>>
>>>> }
>>>>
>>>> Its starting to get hard and harder to read IMO.
>>>>
>>>> Although perhaps the reverse could be come sort of iterator mechanism. You could define what order items are visited.  I mean, reverse would not be a keyword at all and would exist in some library.  Although I'm not sure how it would be implemented, and it may defeat the purpose of foreach_reverse being optimal.
>>>>
>>>> Just a thought.
>>>
>>> shouldn't this perhaps be something like:
>>>
>>> foreach (item; collection) (item2; x->GetColection(b))(item3;
>>> collection3.reverse)
>>> {
>>>
>>> }
>>>
>>>
>>> Now you can select a direction on the each container?
>>>
>>> Naturally, this would avoid performing a copy of the content, and the basic approach is quite easy to handle via a struct containing an opApply(). It would open the door to alternate iteration approaches also, such as skipping entries, merging, or whatever.
>>>
>>> Tango does something vaguely like this for the text-iterators in tango.text.Util
>>
>>
>> What if collection3 is a 40 MB array?
>>
>> The nice thing about foreach_reverse is that it doesn't require any transformations on the data.
> 
> I didn't suggest transformation at all :) Merely a mean of satisfying
> opApply that happens to go backwards instead (or some other pattern).

I realise this, but my point was that 'reverse' on an array *actually* reverses the array.  If we have it return a struct that implements opApply, then people are going to wonder why 'arr.reverse' doesn't reverse the array.

At least with operator overloads, we can keep them separate.

That said, maybe something along the lines of .iterReverse or somesuch would work... but then, it would be nice to not have to stuff around with all these structs :P  *dreams of having Python-style generators*

The other thing to think about is that we shouldn't have to use a member function of a structure when the compiler should *know* how to go backwards over a silly little array.

But then, maybe that's just me :)

	-- Daniel

-- 
int getRandomNumber()
{
    return 4; // chosen by fair dice roll.
              // guaranteed to be random.
}

http://xkcd.com/

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
March 22, 2007
kris wrote:
> Chris Nicholson-Sauls wrote:
>>
>>
>> kris wrote:
>>
>>> janderson wrote:
>>>
>>>> Andrei Alexandrescu (See Website For Email) wrote:
>>>>
>>>>> Derek Parnell wrote:
>>>>>
>>>>>> On Thu, 22 Mar 2007 04:53:26 +0900, Bill Baxter wrote:
>>>>>>
>>>>>>> Here's a random thought:
>>>>>>> What about const vs CONST?
>>>>>>> The upcase version obviously being the more const of the two.
>>>>>>> The original proposal played with punctuation, and we've talked plenty about spelling, but we haven't talked about playing with case.  It would be an odd-ball among keywords, admittedly, but if you asked 100 people which of 'const' and 'CONST' was the most constant you'd probably get 100 votes for 'CONST'.  And he could become good friends with foreach_reverse, the other odd-ball keyword who is disparaged by the other kids because of his obesity and the big staple in his belly button.
>>>>>>
>>>>>>
>>>>>>
>>>>>> LOL ... Now that *is* funny.
>>>>>
>>>>>
>>>>>
>>>>> Yah :o). Speaking of foreach_reverse, probably it would be wise to lobby Walter to deprecate it in favor of foreach(reverse) (item ; collection) { ... }. The keyword(extra) syntax is definitely becoming a D signature syntax.
>>>>>
>>>>>
>>>>> Andrei
>>>>
>>>>
>>>>
>>>> //Using your other suggestion:
>>>> foreach(reverse) (item ; collection) (item2 ; x->GetColection(b)) (item3 ; collection3)
>>>> {
>>>>
>>>> }
>>>>
>>>> Its starting to get hard and harder to read IMO.
>>>>
>>>> Although perhaps the reverse could be come sort of iterator mechanism. You could define what order items are visited.  I mean, reverse would not be a keyword at all and would exist in some library.  Although I'm not sure how it would be implemented, and it may defeat the purpose of foreach_reverse being optimal.
>>>>
>>>> Just a thought.
>>>
>>>
>>> shouldn't this perhaps be something like:
>>>
>>> foreach (item; collection) (item2; x->GetColection(b))(item3; collection3.reverse)
>>> {
>>>
>>> }
>>>
>>
>> Or better still, if we wanted to keep 'reverse' away from the collection:
>>
>> foreach (item; collection) (item2; x->GetColection(b)) (item3; collection3; reverse) {
>> }
>>
>> I wouldn't be above a 'foreach(i,x ; source ; order)' syntax in general, really.
>>
>> -- Chris Nicholson-Sauls
> 
> Except for one thing, Chris; basing the syntax on 'keywords' limits one to what the compiler chooses to support? Basing the opApply() selection on a method/property name instead (with optional arguments also) leaves the door wide open for any implementation you can imagine?

I was actually thinking the third "parameter" should be one of: function, function pointer, delegate, variable containing referance to a delegate; rather than some language-defined set of order keywords.

int reverse   (T,U) (int delegate(U,T) dg) {}
int scattered (T,U) (int delegate(U,T) dg) {}

foreach (i,x ; some_array ; reverse  ) {}
foreach (i,x ; some_array ; scattered) {}

It would seperate ordering algorithms from the collections themselves, and also not prevent that approach so long as the current allowance for delegates and usage of opApply were retained (as, presumably, they would be).  Just a crazy idea.

-- Chris Nicholson-Sauls
March 22, 2007

Chris Nicholson-Sauls wrote:
> kris wrote:
>> Chris Nicholson-Sauls wrote:
>>>
>>>
>>> kris wrote:
>>>
>>>> janderson wrote:
>>>> [snip]
>>>>
>>>
>>> Or better still, if we wanted to keep 'reverse' away from the collection:
>>>
>>> foreach (item; collection) (item2; x->GetColection(b)) (item3;
>>> collection3; reverse) {
>>> }
>>>
>>> I wouldn't be above a 'foreach(i,x ; source ; order)' syntax in
>>> general, really.
>>>
>>> -- Chris Nicholson-Sauls
>>
>> Except for one thing, Chris; basing the syntax on 'keywords' limits one to what the compiler chooses to support? Basing the opApply() selection on a method/property name instead (with optional arguments also) leaves the door wide open for any implementation you can imagine?
> 
> I was actually thinking the third "parameter" should be one of: function, function pointer, delegate, variable containing referance to a delegate; rather than some language-defined set of order keywords.
> 
> int reverse   (T,U) (int delegate(U,T) dg) {}
> int scattered (T,U) (int delegate(U,T) dg) {}
> 
> foreach (i,x ; some_array ; reverse  ) {}
> foreach (i,x ; some_array ; scattered) {}
> 
> It would seperate ordering algorithms from the collections themselves, and also not prevent that approach so long as the current allowance for delegates and usage of opApply were retained (as, presumably, they would be).  Just a crazy idea.
> 
> -- Chris Nicholson-Sauls

I think the third parameter should also be usable as:

> class Foo
> {
>     int opApply_scattered(...) { ... }
> }
>
> foreach (i,x ; new Foo ; scattered) {}

Reason being that if you implement "scattered" as a template, and my class doesn't implement whatever interface you're using, I'm stuffed.

But I do rather like the thought of the third parameter being a function of some description.  Cleanly separates the thing you're iterating over, and *how* you're iterating over it.

	-- Daniel

-- 
int getRandomNumber()
{
    return 4; // chosen by fair dice roll.
              // guaranteed to be random.
}

http://xkcd.com/

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
March 22, 2007
Chris Nicholson-Sauls wrote:
[snip]
> I was actually thinking the third "parameter" should be one of: function, function pointer, delegate, variable containing referance to a delegate; rather than some language-defined set of order keywords.

ah; sorry ... I totally missed that :)
March 22, 2007
kris wrote:
> Chris Nicholson-Sauls wrote:
> [snip]
>> I was actually thinking the third "parameter" should be one of: function, function pointer, delegate, variable containing referance to a delegate; rather than some language-defined set of order keywords.
> 
> ah; sorry ... I totally missed that :)

I totally failed to mention it, I think.  ;)

-- Chris Nicholson-Sauls
March 22, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Yah :o). Speaking of foreach_reverse, probably it would be wise to lobby Walter to deprecate it in favor of foreach(reverse) (item ; collection) { ... }. The keyword(extra) syntax is definitely becoming a D signature syntax.
> 
> 
> Andrei
I'm surprised no-one has mentioned Tom S's proposal back from DMD 0.170: allow trailing delegates to support arbitrary iterating (see http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D.announce&artnum=4940)

It was met with a very positive reaction back then, but nothing ever really came of it.

Basically, it allows iteration styles of any name, as people are suggesting again now, but instead of the foreach(iteration_style)(item; collection) syntax suggested here, you could just write:

    collection.iteration_style (item) { code; }

So you would get things like:

    collection.random_each (i) { writefln(i); }

Feature-wise, this doesn't add much to what people suggest here, but it makes sense when you want to go beyond foreach-style iterators. Also, some things are just better expressed without the 'foreach' there to get in the way:

    5.times { writefln("Hello World!"); }

Let's face it: you can do more stuff with delegates than can be described by saying 'for each element of some set.'

Cheers,

Reiner
March 22, 2007
janderson skrev:

> Walter posted about this in another thread saying foreach_reverse was that way because of some performance nitch.

That's right. The DMD compiler isn't able to inline functions containing loops. Also, it is unable to inline calls to compile time known const (invariant?) delegates. Instead of fixing that, a new special case keyword is introduced.

> I still think that foreach_reverse is not the right way to do a reverse.  I think having it as a member or free function is the best.

I Agree.

> The compiler should be able to detect .reverses on primitive arrays and optimize them.

Or even better, fix the compiler issues with inlining. Here is a trivial reverse array viewer I've been using since long before foreach_reverse was introduced. It doesn't perform extremely well for the above mentioned reasons, but I've always been thinking that one day a decent compiler would generate close to optimal code out of this.

struct ReverseIterator(T:T[]) {
        T[] array;

        int opApply(int delegate(inout T) dg) {
                for (int i = array.length-1; i >= 0; i--) {
                        if (auto status = dg(array[i]))
                                return status;
                }
                return 0;
        }
}

ReverseIterator!(Array) reverseView(Array)(Array array) {
        ReverseIterator!(Array) iter = {array};
        return iter;
}

import std.stdio;
void main() {
        foreach(x; reverseView("abcdx"))
                writefln("%s",x);
}

> Besides, how does the compiler currently optimize something written as an opApply?

It doesn't.

The introduction of foreach_reverse resolved the above mentioned performance issue with iterating backwards over an array, but didn't resolve either:

* Iterating backwards over any other container/view that implements random access semantics.

* Efficiently implementing other view constructs, such as:

foreach(person; employees.select((Person p){ return p.age > 65; }))

foreach(t; str.tokenize(" "))

foreach(d; data.selectIndices(indexArray))

etc...

foreach_reverse doesn't generalize anything. A container that implements random access semantics will not automatically be foreach_reversible. Everyone wanting to make a standard container will have to implement a silly opApplyReverse method that serves no real use. The performance will not be any better than using a generic reverse viewer and this was the only argument for adding foreach_reverse.

IMHO, foreach_reverse is an aberration in so many ways and the sooner it is gone the better.

/Oskar
March 22, 2007
Benji Smith wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Derek Parnell wrote:
>>> On Thu, 22 Mar 2007 04:53:26 +0900, Bill Baxter wrote:
>>>
>>>> Here's a random thought:
>>>> What about const vs CONST?
>>>> The upcase version obviously being the more const of the two.
>>>> The original proposal played with punctuation, and we've talked plenty about spelling, but we haven't talked about playing with case.  It would be an odd-ball among keywords, admittedly, but if you asked 100 people which of 'const' and 'CONST' was the most constant you'd probably get 100 votes for 'CONST'.  And he could become good friends with foreach_reverse, the other odd-ball keyword who is disparaged by the other kids because of his obesity and the big staple in his belly button.
>>>
>>> LOL ... Now that *is* funny.
>>
>> Yah :o). Speaking of foreach_reverse, probably it would be wise to lobby Walter to deprecate it in favor of foreach(reverse) (item ; collection) { ... }. The keyword(extra) syntax is definitely becoming a D signature syntax.
>>
>>
>> Andrei
> 
> What do you call that little non-keyword in parens when you refer to it in your parsing code? If it's not a keyword or an operator or an identifier, how do you refer to it?
> 
> Just curious.

I've always referred to it as a "modifier", almost like how template parameters "modify" the shape/contents/behavior of the enclosing type.  Taking into consideration Andrei's suggestion to your post, perhaps "contextual modifier" might be more appropriate?

-- 
- EricAnderton at yahoo
March 22, 2007
janderson wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Derek Parnell wrote:
>>> On Thu, 22 Mar 2007 04:53:26 +0900, Bill Baxter wrote:
>>>
>>>> Here's a random thought:
>>>> What about const vs CONST?
>>>> The upcase version obviously being the more const of the two.
>>>> The original proposal played with punctuation, and we've talked plenty about spelling, but we haven't talked about playing with case.  It would be an odd-ball among keywords, admittedly, but if you asked 100 people which of 'const' and 'CONST' was the most constant you'd probably get 100 votes for 'CONST'.  And he could become good friends with foreach_reverse, the other odd-ball keyword who is disparaged by the other kids because of his obesity and the big staple in his belly button.
>>>
>>> LOL ... Now that *is* funny.
>>
>> Yah :o). Speaking of foreach_reverse, probably it would be wise to lobby Walter to deprecate it in favor of foreach(reverse) (item ; collection) { ... }. The keyword(extra) syntax is definitely becoming a D signature syntax.
>>
>>
>> Andrei
> 
> I guess one extension to this syntax could be constant iterations (the values in the array don't change:
> 
> foreach (const) (item ; collection)
> {
> 
> }
> 
> I still think
> 
> const foreach (item; collection)
> {
> 
> }
> 
> is better if we did have a feature like this.

Now that I think about it:

foreach (const item; collection)
{

}

is probably best.
March 22, 2007
Reiner Pope wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Yah :o). Speaking of foreach_reverse, probably it would be wise to lobby Walter to deprecate it in favor of foreach(reverse) (item ; collection) { ... }. The keyword(extra) syntax is definitely becoming a D signature syntax.
>>
>>
>> Andrei
> I'm surprised no-one has mentioned Tom S's proposal back from DMD 0.170: allow trailing delegates to support arbitrary iterating (see http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D.announce&artnum=4940) 
> 
> 
> It was met with a very positive reaction back then, but nothing ever really came of it.
> 
> Basically, it allows iteration styles of any name, as people are suggesting again now, but instead of the foreach(iteration_style)(item; collection) syntax suggested here, you could just write:
> 
>     collection.iteration_style (item) { code; }
> 
> So you would get things like:
> 
>     collection.random_each (i) { writefln(i); }
> 
> Feature-wise, this doesn't add much to what people suggest here, but it makes sense when you want to go beyond foreach-style iterators. Also, some things are just better expressed without the 'foreach' there to get in the way:
> 
>     5.times { writefln("Hello World!"); }
> 
> Let's face it: you can do more stuff with delegates than can be described by saying 'for each element of some set.'

Walter is seriously considering this for addition; thanks for bringing it up again.


Andrei