A currying function
Artur Skawina
art.08.09 at gmail.com
Tue Jun 19 05:52:20 PDT 2012
On 06/18/12 22:24, bearophile wrote:
> I think std.functional.curry is badly named because I think it's a "partial application" (I suggest to rename it).
> In Haskell and Scala currying is built-in, this is Haskell, shell (ghci):
>
> Prelude> let foo x y z = x * 2 + y * 3 + y * 5
> Prelude> let foo1 = foo 5
> Prelude> let foo2 = foo1 4
> Prelude> foo2 3
> 42
> So I've written a D version of it below, not tested much. I have not translated the C++11 version. This was quite easy to write, and much simpler and shorter than the C++11 version (but maybe this misses something, this is just a first draft). This kind of stuff was quite longer to do in D1, but now with CTFE on strings ops, defining one or more inner static functions that build a string at compile-time, it's quite easy. Now I don't need lot of templates to do this.
>
> There are two alternative designs, curry1 seems a bit more elegant, but if you want to use it in-place it forces you to add a () at the beginning, that's not nice and intuitive. So probably curry2 is better.
[...]
> I think this code induces the creation of heap allocated closures, so probably a more efficient version is needed:
I'm not really sure when you'd want to use this in D.
But, just to be able to say "Real Programmers don't use mixins": :)
static struct curry(alias F) {
import std.traits;
ParameterTypeTuple!F args;
template opCall1(size_t N=0) {
auto ref opCall1(ParameterTypeTuple!F[N] a) {
auto p = (cast(Unqual!(typeof(a))*)&args[N]);
*p = a;
static if (N==args.length-1)
return F(args);
else
return &opCall1!(N+1);
}
}
alias opCall1!() opCall;
static curry opCall() { curry c; return c; }
}
//...
double foo(immutable int x, in float y, short z=5) pure nothrow {
return x * 2 + y * 3 + y * 5;
}
auto cf = curry!foo();
auto c2 = cf(5)(4);
writeln(c2(3));
curry!foo cf2;
writeln(cf2(5)(4)(3));
writeln(curry!foo()(5)(4)(3));
The empty parens could be omitted, but you'd need a compiler with full
property support for that (and of course would have to wrap this in a
function). No heap allocations, the resulting code could be better
though.
> So this version doesn't handle ref arguments.
Yeah, this one doesn't either; iterating and checking every arg would
probably be necessary.
artur
More information about the Digitalmars-d
mailing list