A functor-based curry

downs default_357-line at yahoo.de
Tue Jan 29 06:20:07 PST 2008


[snip]

Your example doesn't work because a function template must only contain exactly a single defined symbol that has the same name as the template.

Here's a simple functor version:

> import std.stdio, std.traits;
> 

A sample function

> int add(int a, int b, int c) { return a+b+c; }
> 

The initialization of T

> template Init(T) { T Init; }
> 
> class CurryFunctor(C, P...) {
>   C callable;
>   P params;
>   this(C c, P p) {
>     callable = c;
>     foreach (id, v; p) params[id] = v;
>   }

The purpose of this is to allow a kind of automatic return type deduction.
Think of this as the function body of opCall.

>   const string CODE = "
>     static if (is(typeof(callable(params, Init!(R))))) {
>       return callable(params, rest);
>     } else
>       return curry(callable, params, rest);
>   ";

Now we use our function body to determine the return type of opCall, by asking the question:
"If our function were a function literal that took no parameters (declaring rest as a variable;
this is okay because this function literal is never called), then what would its type be?"

>   typeof(mixin("function(){ R rest; "~CODE~" }()")) opCall(R...)(R rest) {
>     mixin(CODE);
>   }
> }
> 

A simple wrapper.

> CurryFunctor!(C, P) curry(C, P...)(C callable, P params) {
>   return new CurryFunctor!(C, P)(callable, params);
> }
> 

And examples.

> void main() {
>   writefln(curry(&add, 2, 3)(5));
>   writefln(curry(&add, 2)(3)(4));
> }

Have fun with it!

 --downs


More information about the Digitalmars-d-learn mailing list