Has the ban on returning function nested structs been lifted?
Simen kjaeraas
simen.kjaras at gmail.com
Sat Mar 19 02:27:46 PDT 2011
On Fri, 18 Mar 2011 23:48:53 +0100, bearophile <bearophileHUGS at lycos.com>
wrote:
> Jonathan M Davis:
>
>> Actually, the coolest part about it IMHO is that it highlights the fact
>> that you
>> should be using auto with std.algorithm and _not_ care about the exact
>> types of
>> the return types. Knowing the exact return type for those functions is
>> generally
>> unnecessary and is often scary anyway (especially with the functions
>> which
>> return lazy ranges like map and until). Making the functions return
>> auto and
>> completely hiding the return type pretty much forces the issue. There's
>> still
>> likely to be some confusion for those new to D, but it makes the proper
>> way to
>> use std.algorithm more obvious. I'd hate to deal with any code which
>> used
>> std.algorithm without auto. That would get ugly _fast_.
>
> auto variable inference is indeed almost necessary if you want to use
> lazy functions as the ones in Phobos. But I have to say that those types
> are scary because of the current design of those Phobos higher order
> functions. In Haskell if you have an iterable and you perform a map on
> it using a function that returns an int, you produce something like a
> [Int], that's a lazy list of machine integers. This is a very simple
> type. If you perform another map on that list, and the mapping function
> returns an int again, the type of the whole result is [Int] still. The
> type you work with doesn't grow more and more as with Phobos functions.
> Designers of C# LINQ have found a more complex solution, they build a
> tree of lazy delegates...
And we can have something similar in D:
struct Range( T ) {
void delegate( ) popFrontDg;
bool delegate( ) emptyDg;
T delegate( ) frontDg;
this( R )( R range ) if ( isForwardRange!R && is( ElementType!R == T )
) {
auto rng = range.save();
popFrontDg = ( ){ rng.popFront(); };
emptyDg = ( ){ return rng.empty; };
frontDg = ( ){ return rng.front; };
}
@property T front( ) {
return frontDg( );
}
@property bool empty( ) {
return emptyDg( );
}
void popFront( ) {
popFrontDg( );
}
}
Range!(ElementType!R) range( R )( R rng ) if ( isForwardRange!R ) {
return Range!(ElementType!R)( rng );
}
There are times when I've wanted something like this because I don't
know the resultant type of a bunch of range operations, but have to
save it in a struct or class.
--
Simen
More information about the Digitalmars-d
mailing list