View mode: basic / threaded / horizontal-split · Log in · Help
January 25, 2005
Nested functions as delegated iterators
Proposal:

To make use of the powerfull delegate and nested function features, a 
change in syntax could simplify the usage of these functions. These 
could then be used as iterators.

By combining delegates, iterators and nested functions the compiler 
changes should remain minimal. A simple substitution should be enough. 
As an example we will take a simple class called Mapping which maps 
char[] to char[]. The Mapping class has to iterators: each and filter.

class Mapping
{
    void filter ( bool delegate( char[] key, char[] value) dg )
    void each( void delegate( char[] key, char[] value) dg )
}

Then we could write in a main function:

Mapping m = new Mapping( mapping );
bool my_iterator(char[] key, char[] value) {
    return key == value;
}
m.filter( &my_iterator );

void my_dump_iterator(char[] key, char[] value) {
    printf("key: %.*s value: %.*s\n", key, value);
}
m.each( &my_dump_iterator );

But this is very tidious, because you have got to invent names each 
time. A nicer approuch would be:

m.filter() thru (char[] key, char[] value) { return key == value; }
m.each() thru (char[] key, char[] value) {
	printf("key: %.*s value: %.*s\n", key, value);
}

Which is also easier to read because the bodies follow the iterator.

The compiler can find the right iterator functions by appending the 
delegate to the argument list. The return value is deduced from the 
iterator delegate function. And a nested function could be created as above.

You might recognise these constructs from scheme or ruby, thanks to 
nested functions and delegates it is also possible in D. ;)

Another nice construct:

File.open("file.txt") thru ( File f ) {
    ... do things while file is open ...
} // file is closed after body is executed.

I would have used the "with" keyword if it was not occupied ;) If anyone 
can think of a better one?

Daan Oosterveld
January 25, 2005
Re: Nested functions as delegated iterators
"Daan Oosterveld" <daan.oosterveld@home.nl> wrote in message 
news:ct65na$29r3$1@digitaldaemon.com...
> Proposal:
>
> To make use of the powerfull delegate and nested function features, a 
> change in syntax could simplify the usage of these functions. These could 
> then be used as iterators.
>
> By combining delegates, iterators and nested functions the compiler 
> changes should remain minimal. A simple substitution should be enough. As 
> an example we will take a simple class called Mapping which maps char[] to 
> char[]. The Mapping class has to iterators: each and filter.
>
> class Mapping
> {
>     void filter ( bool delegate( char[] key, char[] value) dg )
>     void each( void delegate( char[] key, char[] value) dg )
> }
>
> Then we could write in a main function:
>
> Mapping m = new Mapping( mapping );
> bool my_iterator(char[] key, char[] value) {
>     return key == value;
> }
> m.filter( &my_iterator );
>
> void my_dump_iterator(char[] key, char[] value) {
>     printf("key: %.*s value: %.*s\n", key, value);
> }
> m.each( &my_dump_iterator );
>
> But this is very tidious, because you have got to invent names each time.

Technically one doesn't have to invent names since currently one can write 
anonymous delegates:
m.filter(delegate bool(char[] key, char[] value) {return key == value;} );

See http://www.digitalmars.com/d/expression.html#FunctionLiteral
The syntax ends up looking pretty similar to your proposal.

[snip]
January 25, 2005
Re: Nested functions as delegated iterators
Daan Oosterveld wrote:
> Proposal:
> 
> To make use of the powerfull delegate and nested function features, a 
> change in syntax could simplify the usage of these functions. These 
> could then be used as iterators.
> 
> By combining delegates, iterators and nested functions the compiler 
> changes should remain minimal. A simple substitution should be enough. 
> As an example we will take a simple class called Mapping which maps 
> char[] to char[]. The Mapping class has to iterators: each and filter.
> 
> class Mapping
> {
>     void filter ( bool delegate( char[] key, char[] value) dg )
>     void each( void delegate( char[] key, char[] value) dg )
> }
> 
> Then we could write in a main function:
> 
> Mapping m = new Mapping( mapping );
> bool my_iterator(char[] key, char[] value) {
>     return key == value;
> }
> m.filter( &my_iterator );
> 
> void my_dump_iterator(char[] key, char[] value) {
>     printf("key: %.*s value: %.*s\n", key, value);
> }
> m.each( &my_dump_iterator );
> 
> But this is very tidious, because you have got to invent names each 
> time. A nicer approuch would be:
> 
> m.filter() thru (char[] key, char[] value) { return key == value; }
> m.each() thru (char[] key, char[] value) {
>     printf("key: %.*s value: %.*s\n", key, value);
> }

I believe that what you are trying to do can be done already, with 
delegate literals!

m.filter(delegate bool(char[] key,char[] value)
             { return key == value; }
        );
m.each(delegate void(char[] key,char[] value)
             { printf("key: %.*s value: *.*s\n", key,value); }
      );
January 26, 2005
Re: Nested functions as delegated iterators
Ben Hinkle schreef:
> "Daan Oosterveld" <daan.oosterveld@home.nl> wrote in message 
> news:ct65na$29r3$1@digitaldaemon.com...
> 
>>Proposal:
>>
>>To make use of the powerfull delegate and nested function features, a 
>>change in syntax could simplify the usage of these functions. These could 
>>then be used as iterators.
>>
>>By combining delegates, iterators and nested functions the compiler 
>>changes should remain minimal. A simple substitution should be enough. As 
>>an example we will take a simple class called Mapping which maps char[] to 
>>char[]. The Mapping class has to iterators: each and filter.
>>
>>class Mapping
>>{
>>    void filter ( bool delegate( char[] key, char[] value) dg )
>>    void each( void delegate( char[] key, char[] value) dg )
>>}
>>
>>Then we could write in a main function:
>>
>>Mapping m = new Mapping( mapping );
>>bool my_iterator(char[] key, char[] value) {
>>    return key == value;
>>}
>>m.filter( &my_iterator );
>>
>>void my_dump_iterator(char[] key, char[] value) {
>>    printf("key: %.*s value: %.*s\n", key, value);
>>}
>>m.each( &my_dump_iterator );
>>
>>But this is very tidious, because you have got to invent names each time.
> 
> 
> Technically one doesn't have to invent names since currently one can write 
> anonymous delegates:
> m.filter(delegate bool(char[] key, char[] value) {return key == value;} );
> 
> See http://www.digitalmars.com/d/expression.html#FunctionLiteral
> The syntax ends up looking pretty similar to your proposal.
> 
> [snip]
> 
> 

Hmm,

I overlooked that part of the documentation. GREAT! But still my C/C++ 
background doesn't like to put {} inside () because it looks ugly and it 
is cluttering. ;)

Same for C (and D) we use variadic functions to reduce clutter. We don't 
have to write things like this:

printf("key: %.*s value: %.*s\n", [
	cast(void *) key, cast(void *) value
]);

or:

printf("key: %.*s ", key );
printf("value: %.*s\n", value );

Which also reduces clutter and makes the source more readable. Same 
thing for delegate literals:

m.filter( delegate bool(char[] key, char[] value) {
	return key == value;
} );

looks more cluttered as this:

m.filter() thru (char[] key, char[] value) {return key == value;}

(and we don't even need funky function calls like variadic functions 
need to decrypt the argument list)
With an more complex program the clutter becomes a mess:

RegExp ereg = new RegExp("^import","");
File.open("textfile", delegate (File f) {
	f.each_line( delegate (char[] l) {
		if (ereg.match( l )) {
			... extract import statements ...
		}
	} );
} );

It is difficult to see where the ");" comes from. Whereas writen with a 
different syntax the program is more readable.

RegExp ereg = new RegExp("^import","");
File.open("textfile") thru (File f) {
	f.each_line() thru (char[] l) {
		if (ereg.match( l )) {
			... extract import statements ...
		}
	}
}

Given the right classes and member functions writing small programs 
becomes very easy (and nice to look at)

Daan
Top | Discussion index | About this forum | D home