Magnus Lie Hetland <mag...@hetland.org> wrote:

Might I also ask why you use an out parameter instead of a tuple return?

Well... I had a tuple return at first, but one of the advantages of returning multiple values that I'm accustomed to is the ability to assign to multiple variables, such as

  arg, val = minArg(...)

(Yeah, I'm a Python guy... ;)

As far as I can see, you can't do that here? Using result[0] and result[1] or the like, or assigning separately to two variables just seemed more cumbersome. Then again, I could use a tuple with named members, I guess. In your opinion, what would be the prettiest (in D terms) way of doing this?

You might want to try more from dranges - the reftuple:

_(arg,val) = minArg(...);

It resides in dranges.reftuple, and still has some warts, but it
usually works.

This is also a possible implementation (coded in about 5 minutes, gives
no nice error messages, but it seems to work :p ):


import std.typetuple;
import std.typecons;

template TypeOf( alias T ) {
    alias typeof( T ) TypeOf;
}

@property void _( T... )( Tuple!( staticMap!(TypeOf, T) ) args ) {
    foreach ( i, e; T ) {
        e = args[i];
    }
}

void main( ) {
    int a, b;
    _!(a,b) = tuple(b,a+b); // fibonacci
}


I see. I actually don't mind writing nested templates myself -- but for some reason I couldn't get them to work properly. (D kept complaining about declarations vs instances, and the like; I guess I'll have a look at how dranges does it.)

Yeah. D has the nice Eponymous Template Trick, but it sadly only works
for one level. :(


By the way, if you have suggestions for other more "D-like" ways of encapsulating this functionality (basically a linear scan for an element that yields a max/min value for a given expression), I'd be interested to hear that too. The best way to solve a problem is often to rephrase it :)

So you have to test for every single element of the range?

If so, I think this works:


module foo;

import std.typecons;
import std.functional;
import std.array;

template optArg( alias pred ) {
    template optArg( alias fn ) {
        auto optArg( Range )( Range r ) {
            alias binaryFun!pred predicate;
            alias unaryFun!fn func;

            auto result = tuple( r.front, func( r.front ) );
            foreach ( e; r ) {
                auto tmp = func( e );
                if ( predicate( e, result[1] ) ) {
                    result = tuple( e, tmp );
                }
            }
            return result;
        }
    }
}

void main( ) {
    alias optArg!"a<b" minArg;
    alias minArg!"a" foo;
    assert( foo( [5,2,1,3] ) == tuple(1,1) );
}



--
Simen

Reply via email to