44

Given a method DoSomething that takes a (parameterless) function and handles it in some way. Is there a better way to create the "overloads" for functions with parameters than the snippet below?

public static TResult DoSomething<TResult>(Func<TResult> func)
{
    //call func() and do something else
}

public static TResult DoSomething<T0, TResult>(
    Func<T0, TResult> func,
    T0 arg0)
{
    return DoSomething(() => func(arg0));
}

public static TResult DoSomething<T0, T1, TResult>(
    Func<T0, T1, TResult> func,
    T0 arg0, T1 arg1)
{
    return DoSomething(arg => func(arg, arg1), arg0);
}

public static TResult DoSomething<T0, T1, T2, TResult>(
    Func<T0, T1, T2, TResult> func,
    T0 arg0, T1 arg1, T2 arg2)
{
    return DoSomething(arg => func(arg, arg1, arg2), arg0);
}
Rauhotz
  • 7,914
  • 6
  • 40
  • 44
  • 1
    Here are a couple posts that might be interesting if you're trying to curry in C#: http://blogs.msdn.com/wesdyer/archive/2007/01/29/currying-and-partial-function-application.aspx http://diditwith.net/2007/10/23/BuildingFunctionsFromFunctionsPart2FunctionComposition.aspx – Jay Bazuzi Jan 04 '09 at 20:26
  • 1
    Did you check this blog post? [http://mikehadlow.blogspot.com/2008/03/currying-in-c-with-oliver-sturm.html](http://mikehadlow.blogspot.com/2008/03/currying-in-c-with-oliver-sturm.html) – rodbv Jan 04 '09 at 20:05
  • +1 for the wesdyer link - you'll get a really solid understanding of a few lesser understood concepts if you also read the related Fibonacci post: http://blogs.msdn.com/b/wesdyer/archive/2007/02/02/anonymous-recursion-in-c.aspx – Jordan Feb 12 '14 at 01:59
  • msdn links are broke. – Alan Baljeu Apr 08 '19 at 15:31

3 Answers3

43

EDIT: As noted in comments, this is partial application rather than currying. I wrote a blog post on my understanding of the difference, which folks may find interesting.

Well, it's not particularly different - but I'd separate out the currying part from the "calling DoSomething" part:

public static Func<TResult> Apply<TResult, TArg> (Func<TArg, TResult> func, TArg arg)
{
    return () => func(arg);
}

public static Func<TResult> Apply<TResult, TArg1, TArg2> (Func<TArg1, TArg2, TResult> func,
                                                          TArg1 arg1, TArg2 arg2)
{
    return () => func(arg1, arg2);
}

// etc

Then:

DoSomething(Apply(foo, 1));

That way you can reuse the currying code in other situations - including cases where you don't want to call the newly-returned delegate immediately. (You might want to curry it more later on, for example.)

Peter Wishart
  • 11,600
  • 1
  • 26
  • 45
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Why do you return Func instead of Func> ? – Paco Jan 04 '09 at 20:17
  • 2
    Because Func is what you want to be able to pass into DoSomething. The idea is that the Curry method should take a function which takes some parameters, as well as values for those parameters, and return a function which takes fewer parameters (0 in this case). – Jon Skeet Jan 04 '09 at 20:26
  • I thought the idea was that a Func was should be converted to a function with less parameters Func>. You can create a default dosomething with a lot of parameters and curried variants – Paco Jan 04 '09 at 20:34
  • But Func> is a function which *takes* a TResult and returns a Func. Yes, you want to reduce the number of parameters - but by supplying the values, not by dealing with functions to convert from one argument type to another. – Jon Skeet Jan 04 '09 at 20:38
  • But you can use a func like () => "myValue" – Paco Jan 04 '09 at 20:41
  • @Paco: Yes, you can if you only want to use it in a single place. If you want to be able to use the resulting function several times, currying it explicitly can be helpful. It's nothing magical - you could use the body of the Curry method anywhere that you called the method - but it's just handy. – Jon Skeet Jan 04 '09 at 20:49
  • The problem is see with the separate Curry function is that i push the work from me to the user of my code. Where to place the Curry function? There aren't global functions in C#. – Rauhotz Jan 04 '09 at 23:34
  • Yes, it's the Math.Sin problem again. Java's static imports are a nice solution to this. I do think it's nicer to have it in one place than duplicating this for each method that it might be applicable for though. – Jon Skeet Jan 05 '09 at 09:39
  • I'll try if extension methods like public static Func Curry(this Func func, T0 arg0) work – Rauhotz Jan 05 '09 at 11:40
  • Unfortunately extension methods don't work on lambda expressions: http://msmvps.com/blogs/jon_skeet/archive/2008/01/08/extension-methods-on-lamdba-expressions-don-t-work-unfortunately.aspx – Jon Skeet Jan 05 '09 at 12:40
  • 1
    I agree with Paco. IMO this solution does partial application, not currying. See http://lambda-the-ultimate.org/node/2266 – Mauricio Scheffer Jan 13 '09 at 16:15
  • However, the solution fits the question – Mauricio Scheffer Jan 13 '09 at 16:17
  • I suspect that both myself and the original questioner are confused as to what currying means. It sounds like a lot of the rest of the world is too. Interesting question: is it too late to rescue the term? Should we give up on it and start with the same definition, but for a new term? Sounds awful.. – Jon Skeet Jan 13 '09 at 16:25
  • 1
    I see there's even a question here on SO to disambiguate: http://stackoverflow.com/questions/218025/what-is-the-difference-between-currying-and-partial-application – Mauricio Scheffer Jan 13 '09 at 17:56
  • Cool - that's a much clearer explanation than I've seen elsewhere :) – Jon Skeet Jan 13 '09 at 18:36
  • in light of the disambiguation question, is the given code Partial Application or currying? – Maslow Sep 03 '13 at 19:10
  • @Maslow: Partial application, I think. See the blog post I've now referenced. – Jon Skeet Sep 03 '13 at 20:49
  • public static Func> Curry(this Func spin) { return makes => my => spin(makes, my); } – Jordan Feb 12 '14 at 01:41
4

The @Jon Skeet answer is right, but write by hand all possibles overload is something insane, so you can use a lib like Curryfy that do this job for you. Curryfy lib particularly exposes Curry, UnCurry and ApplyPartial extension methods, with a lot of overloads.

leandromoh
  • 139
  • 6
2

Here is the method that allows to write unlimited calls of functions using dynamic (like Curry in js):

dynamic Sum(int a)
{
    Console.WriteLine(a);
    return new Func<int, dynamic>(b => Sum(a + b));
}

If you call it like this Sum(2)(3)(4)(10) the output will be:

2
5
9
19
Rodion Mostovoi
  • 1,205
  • 12
  • 16