View mode: basic / threaded / horizontal-split · Log in · Help
October 17, 2006
Re: DMD 0.170 release
Reiner Pope wrote:
> Tom S wrote:
>> void each(int[] a, void delegate(int) dg, inout void* ret) {
> It would be good to support non-void delegates as well, for things with 
> predicates, like map, fold, and sort:
> 
>  int fold(int[] a, int start, void delegate(int, int) dg, inout void* ret)
> 
>  and
> 
>  fold(myList, 0) (a, b) { yield a + b; } // Yield returns a value from 
> the delegate, as opposed to returning from the enclosing function

I think it's a great idea and it adds a whole new dimension to the 
proposal !


> Note that with some predicates shouldn't be able to control the flow of 
> code, so I think that last parameter (inout void* ret) should be 
> optional -- if the last parameter is a delegate, then break and return 
> can't be used within the delegate.

Another good idea :)


>>     each (arr) (int a) {
> Of course, this should be type-inferred so you just need to write
> 
> each (arr) (a) { ... }
>   or
> arr.each (a) { ... }

Sure thing :)


I'm not yet fully convinced if trailing delegates should be allowed 
implicitly, just because a function's signature matches some criteria. A 
special keyword like 'trailing' could be used for it. Of course, because 
of a lack of a better keyword at the moment, we could just call it 
'static' <g>


--
Tomasz Stachowiak
October 17, 2006
Re: interface function isn't implemented - was Re: DMD 0.170 release
Chris Miller wrote:
> On Tue, 17 Oct 2006 18:17:33 -0400, Walter Bright 
> <newshound@digitalmars.com> wrote:
> 
>> Frank Benoit (keinfarbton) wrote:
>>> see bug report 440
>>
>> Does that need a fix right away?
> 
> Broke a lot of my projects; went back to DMD 0.169 for now.

Mango, or parts of it, are also broken by this unfortunatly.
October 17, 2006
Re: DMD 0.170 release
Vladimir Kulev wrote:
> J Duncan wrote:
>> Disagree with you, its a nice thing to have.
> 
> There are many things which are nice to have, but only really essential ones
> should be in language itself. Reverse foreach can be implemented in other
> way.

So can ordinary foreach.

Stewart.

-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d- s:-@ C++@ a->--- UB@ P+ L E@ W++@ N+++ o K-@ w++@ O? M V? PS- 
PE- Y? PGP- t- 5? X? R b DI? D G e++++ h-- r-- !y
------END GEEK CODE BLOCK------

My e-mail is valid but not my primary mailbox.  Please keep replies on 
the 'group where everyone may benefit.
October 17, 2006
Re: DMD 0.170 release
Walter Bright wrote:
> John Reimer wrote:
>> I have to agree with Sean and Ary.  My own opinion: I don't really
>> understand why "foreach_reverse" was, once again, just tossed into
>> the language with (what seems to be) a minimum of discussion?
> 
> There was quite a bit of discussion. The thread was a bit old, but that 
> doesn't make it less relevant:
> 
> http://www.digitalmars.com/d/archives/digitalmars/D/17320.html
> 
>> Well, will you look at that.  Isn't that irony?  We got our rolls
>> reversed, I think.  I used to be Walter that was hesitant to add
>> keywords to the language.  Go figure! :D
> 
> I was reluctant to do it for a long time for that reason. It's just that 
> no better solution emerged.

To me "for each" had the implication of an unordered 
traversal, with the undertone that *sometime* when 
multi-processor machines became more prominent each iteration 
might be done on a different processor.

I'm aware that this was never the real intent...but that's the 
subtext that I got when I read the code.  This is partially 
out of a desire to allow multi-processor systems to be used 
efficiently.  (What did Intel say?  64 cores/chip in 10 years?)

Perhaps another syntax to denote this will show up.  (Each 
function or subroutine call, perhaps?  But that doesn't imply 
parallelism.)

Sorry, just a reaction.
October 17, 2006
Re: DMD 0.170 release
Tom S wrote:
> ----
> 
> void each(int[] a, void delegate(int) dg, inout void* ret) {
>     for (int i = 0; i < a.length; ++i) {
>         dg(a[i]);
>         if (ret) return;
>     }
> }
> 
> 
> char[] foo() {
>     int[] arr;
>     arr ~= 5;
>     arr ~= 3;
>     arr ~= 2;
>     arr ~= 6;
> 
>     each (arr) (int a) {
>         if (1 == a) return "blah";
>         if (2 == a) return "hmm";
>         if (3 == a) break;
>     }
> 
>     return null;
> }
> 
> 
> void main() {
>     char[] str = foo();
>     printf("foo returned: %.*s\n", str);
> }
> 
> ----
> 
> 
> into:
> 
> 
> ----
> 
> void* CONTINUE    = cast(void*)0;
> void* BREAK        = cast(void*)1;
> 
> 
> void each(int[] a, void delegate(int) dg, inout void* ret) {
>     for (int i = 0; i < a.length; ++i) {
>         dg(a[i]);
>         if (ret) return;
>     }
> }
> 
> 
> char[] foo() {
>     int[] arr;
>     arr ~= 5;
>     arr ~= 2;
>     arr ~= 3;
>     arr ~= 6;
> 
>     {
>         char[]    retCode;
>         void*    ret;
> 
>         each(arr, (int a) {
>             if (1 == a) { retCode = "blah";    ret = &retCode; return; }
>             if (2 == a) { retCode = "hmm";    ret = &retCode; return; }
>             if (3 == a) { ret = BREAK; return; }
>         }, ret);
> 
>         if (ret !is BREAK && ret !is CONTINUE) return *cast(char[]*)ret;
>     }
> 
>     return null;
> }
> 
> 
> void main() {
>     char[] str = foo();
>     printf("foo returned: %.*s\n", str);
> }

That's a lot like how foreach is implemented now <g>.
October 17, 2006
Re: DMD 0.170 release
Stewart Gordon wrote:
> Vladimir Kulev wrote:
>> J Duncan wrote:
>>> Disagree with you, its a nice thing to have.
>>
>> There are many things which are nice to have, but only really 
>> essential ones
>> should be in language itself. Reverse foreach can be implemented in other
>> way.
> 
> So can ordinary foreach.

All you really need is if and goto!
October 18, 2006
Re: DMD 0.170 release
Bill Baxter wrote:
> Is there any reason for not allowing a function to be used too?
> Then you could also use a closure as the thing that does the iteration:

Ok, I just realized that "delegate" can also be pointer to a non-static 
nested function...  Duh.  So my question should have been -- why doesn't 
this work?

int delegate(int delegate(inout ElemT))
reversed(AggregateT,ElemT)(AggregateT array)
{
    int _innerFunc(int delegate(inout ElemT) loopBody)
    {
        int done = 0;
        for (int i = array.length-1; i >=0; i--)
        {
            done = loopBody(array[i]);
            if (done)
                break;
        }
        return done;
    }
    return &_innerFunc;
}
  ...
foreach(real r; reversed!(real[],real)(areal))
{...}

Compiles but gives:
"Error: Access Violation"

I'm not totally clear on how pointers/objects are handled in D.  It 
looks the call to reversed() is maybe creating a copy of the data?  If I 
put in printfs the pointer value is different from that of the original 
int[].

--bb
October 18, 2006
Re: DMD 0.170 release
Bill Baxter wrote:
> Bill Baxter wrote:
>> Is there any reason for not allowing a function to be used too?
>> Then you could also use a closure as the thing that does the iteration:
> 
> Ok, I just realized that "delegate" can also be pointer to a non-static 
> nested function...  Duh.  So my question should have been -- why doesn't 
> this work?
> 
> int delegate(int delegate(inout ElemT))
> reversed(AggregateT,ElemT)(AggregateT array)
> {
>     int _innerFunc(int delegate(inout ElemT) loopBody)
>     {
>         int done = 0;
>         for (int i = array.length-1; i >=0; i--)
>         {
>             done = loopBody(array[i]);
>             if (done)
>                 break;
>         }
>         return done;
>     }
>     return &_innerFunc;
> }
>   ...
> foreach(real r; reversed!(real[],real)(areal))
> {...}
> 
> Compiles but gives:
> "Error: Access Violation"
> 
> I'm not totally clear on how pointers/objects are handled in D.  It 
> looks the call to reversed() is maybe creating a copy of the data?  If I 
> put in printfs the pointer value is different from that of the original 
> int[].

Basically, when you leave 'reversed', any stack data defined within that 
function becomes invalid, as D doesn't support real closures. What 
you're aiming for can be achieved without the new feature anyway, e.g. 
through:

----
import std.stdio;


struct reverse__(AggregType) {
	alias typeof(AggregType[0]) ElemType;
	AggregType arr;
	int opApply(int delegate(inout ElemType) dg) {
		int ret = 0;
		for (int i = arr.length -1; i >= 0; --i){
			ret = dg(arr[i]);
			if (ret) break;
		}
		return ret;
	}
}

reverse__!(T) reverse(T)(T x) {
	reverse__!(T) res;
	res.arr = x;
	return res;
}


void main() {
	char[] foo = "foo bar";
	foreach (c; foo.reverse) {
		writefln(c);
	}
}
----



--
Tomasz Stachowiak
October 18, 2006
Re: DMD 0.170 release
Walter Bright wrote:
> John Reimer wrote:
>> Ah, ok.  I stand corrected on that aspect of my critique.
> 
> I'll give some more lame justifications:
> ...
> So I've been interested in having D algorithms and collections not need 
> iterator types at all. I've been experimenting with doing STL's 
> algorithms in D, and it became clear that to make them complete, reverse 
> iteration was necessary. foreach handles forward iteration, and opIndex 
> handles random access. Various ways of doing reverse traversal without 
> core support always seemed to involve creating dummy classes and other 
> hackish stuff. Promoting it to a supported statement makes it pretty 
> clean for the user to understand and use.
> 
> Essentially, I think foreach_reverse is the missing piece to be able to 
> implement all of STL's algorithms code for D.

I don't see how it helps.  If you can already do:
   foreach(T item; &collection.reversed()) { }

isn't that alone enough to be able to implement all of STL's algorithms 
without adding a "foreach_reverse"?

In fact I'd argue that adding foreach_reverse does nothing more to make 
STL algorithms implementable.  If I'm trying to implement something like 
std::copy, how is foreach_reverse going to help me do that generically? 
 Users can't pass 'foreach_reverse' in as an argument if they want to 
make a backwards copy of something.  But they can certainly pass 
&collection.reversed() in as one.

And -- wouldn't it be nice if the original designer of the class forgot 
to write a reversed(), if I could write one and do
   foreach(T item; reversed(collection)) { }
(without dummy classes and hackish stuff being required). :-)

--bb
October 18, 2006
Re: DMD 0.170 release
Tom S wrote:
> Bill Baxter wrote:
>> Bill Baxter wrote:
>>> Is there any reason for not allowing a function to be used too?
>>> Then you could also use a closure as the thing that does the iteration:
>>
>> Ok, I just realized that "delegate" can also be pointer to a 
>> non-static nested function...  Duh.  So my question should have been 
>> -- why doesn't this work?
>>
>> int delegate(int delegate(inout ElemT))
>> reversed(AggregateT,ElemT)(AggregateT array)
>> {
>>     int _innerFunc(int delegate(inout ElemT) loopBody)
>>     {
>>         int done = 0;
>>         for (int i = array.length-1; i >=0; i--)
>>         {
>>             done = loopBody(array[i]);
>>             if (done)
>>                 break;
>>         }
>>         return done;
>>     }
>>     return &_innerFunc;
>> }
>>   ...
>> foreach(real r; reversed!(real[],real)(areal))
>> {...}
>>
>> Compiles but gives:
>> "Error: Access Violation"
>>
>> I'm not totally clear on how pointers/objects are handled in D.  It 
>> looks the call to reversed() is maybe creating a copy of the data?  If 
>> I put in printfs the pointer value is different from that of the 
>> original int[].
> 
> Basically, when you leave 'reversed', any stack data defined within that 
> function becomes invalid, as D doesn't support real closures. What 
> you're aiming for can be achieved without the new feature anyway, e.g. 
> through:
> 
> ----
> import std.stdio;
> 
> 
> struct reverse__(AggregType) {
>     alias typeof(AggregType[0]) ElemType;
>     AggregType arr;
>     int opApply(int delegate(inout ElemType) dg) {
>         int ret = 0;
>         for (int i = arr.length -1; i >= 0; --i){
>             ret = dg(arr[i]);
>             if (ret) break;
>         }
>         return ret;
>     }
> }
> 
> reverse__!(T) reverse(T)(T x) {
>     reverse__!(T) res;
>     res.arr = x;
>     return res;
> }
> 
> 
> void main() {
>     char[] foo = "foo bar";
>     foreach (c; foo.reverse) {
>         writefln(c);
>     }
> }

Did you mean
   foreach (c; reverse(foo)) ??
I guess so.  it does seem to compile that way.

I think this falls into Walter's "dummy classes and hackish stuff" 
category though.

Is there no way to make something similar work with a nested function? 
If my reversed function above could just get the pointer to the actual 
array then it seems like it should work.  Is there some way to declare 
the AggregateT array parameter so that that happens?

--bb
3 4 5 6 7 8 9 10 11
Top | Discussion index | About this forum | D home