Skip to content

Instantly share code, notes, and snippets.

@e10s
Last active August 29, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save e10s/b470e937dd8afe701bfe to your computer and use it in GitHub Desktop.
Save e10s/b470e937dd8afe701bfe to your computer and use it in GitHub Desktop.
Currying in D
/*
Copyright electrolysis 2015.
Distributed under the Boost Software License, Version 1.0.
(See copy at http://www.boost.org/LICENSE_1_0.txt)
*/
module curry;
import std.traits : arity;
///
template curry(alias func) if(arity!func > 0){
import std.traits : ParameterTypeTuple;
alias PTT = ParameterTypeTuple!func;
auto impl(T...)(T args){
static if(T.length == PTT.length){
return func(args);
}
else{
// Not CTFEable...
return (PTT[T.length] a) => impl(args, a);
}
}
enum curry = (PTT[0] a) => impl(a);
}
///
unittest{
long multiaryFunc(int x, byte y, ubyte z) pure{
return x * y * z;
}
auto unaryFunc(string str) pure{
return str ~ "?";
}
auto templateFunc(S)(S str) pure{
return str ~ "!";
}
assert(curry!multiaryFunc(2)(3)(5) == multiaryFunc(2, 3, 5)); // NOT CTFEable
static assert(curry!unaryFunc("hello") == unaryFunc("hello")); // CTFEable
static assert(curry!(templateFunc!dstring)("hello"d) // Instantiation is required
== templateFunc("hello"d));
// Note a function must not be niladic or variadic
int niladic(){return 5;}
int variadic(int x ...){return x;}
// curry!niladic; // Not applicable
// curry!variadic; // Ditto
// Of course, the intermediate states are portable
alias f = curry!multiaryFunc;
auto f_5 = f(5);
auto f_5_4 = f_5(4);
auto f_5_7 = f_5(7);
assert(f_5_4(2) == 40);
assert(f_5_7(3) == 105);
// Curried closure
auto c_2_k_4 = {
auto k = 1;
auto d_2 = curry!((int a, int b) => a + b + k)(2);
assert(d_2(5) == 8);
k = 4;
assert(d_2(5) == 11);
return d_2;
}();
assert(c_2_k_4(5) == 11);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment