On Tuesday, 18 August 2015 at 14:25:34 UTC, Roland Hadinger wrote:
Hi!
Suppose I wanna do this (which already works, which is why D is
pretty cool):
import std.traits;
import std.typecons : Nullable;
// Retrofit Nullable to allow for monadic chaining
//
auto apply( alias fun, T )( Nullable!T nullable )
if( isSomeFunction!fun )
{
enum returnsVoid = is( ReturnType!fun == void );
enum returnsNullable = is( ReturnType!fun : Nullable!X,
X );
static if( returnsVoid ) {
if( !nullable.isNull )
fun( nullable.get );
} else static if( returnsNullable ) {
alias NR = ReturnType!fun;
if( nullable.isNull )
return NR();
else
return fun( nullable.get );
} else {
alias NR = Nullable!( ReturnType!fun );
if( nullable.isNull )
return NR();
else
return NR( fun( nullable.get ) );
}
}
void main()
{
Nullable!int a = 1;
Nullable!int b = a.apply!( (int x) => 2 * x );
// .apply!( (double x) => foo( x, u ) )
// .apply!( (double x) => bar( x, v ) )
// .apply!( (string x) => baz( x, w ) );
}
...but without explicitly specifying the type of the lambda
parameter:
void main()
{
Nullable!int a = 1;
Nullable!int b = a.apply!( x => 2 * x );
// .apply!( x => foo( x, u ) )
// .apply!( x => bar( x, v ) )
// .apply!( x => baz( x, w ) );
}
Problem is, the shorter form involves lambda templates, and
both 'isSomeFunction' and 'ReturnType' currently don't seem to
work
with those. No problems with the other version.
Can I fix my 'apply' function to still allow for the less
verbose form?
If that's impossible, is it a theoretical possibility to
improve D's type deduction to handle this?
Or should I just not attempt to write code like this for the
time being (after all, functional code like this incurs some
overhead, but in this particular case, I'd prefer legibility
over performance)?
Thanks!
for simple lambdas like that (i.e. function templates with one
template arguments that corresponds to the type of the first and
only argument), just add this template overload:
auto apply( alias fun, T )( Nullable!T nullable )
if( !isSomeFunction!fun )
{
return .apply!(fun!T, T)(nullable);
}
and it should work (give or a take a few typos on my part).