Has the ban on returning function nested structs been lifted?

Jonathan M Davis jmdavisProg at gmx.com
Sat Mar 19 03:18:17 PDT 2011


On Saturday 19 March 2011 02:27:46 Simen kjaeraas wrote:
> 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.

typeof is your friend.

- Jonathan M Davis


More information about the Digitalmars-d mailing list