Partially instantiating templates?
Simen kjaeraas
simen.kjaras at gmail.com
Mon Jan 31 06:50:41 PST 2011
Magnus Lie Hetland <magnus at 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
More information about the Digitalmars-d-learn
mailing list