ようこそ。睡眠不足なプログラマのチラ裏です。

カレー好きのための、ラムダ式でカリー化な拡張メソッド。

以前、C#2.0の匿名メソッドによるカリー化 という記事を書きました。



では、C#3.0ではどうなるのでしょう。


もちろんC#3.0でも匿名デリゲートを使うことはできますが、C#3.0であればやはりラムダ式です。
記述が簡潔になって、より直感的で分かりやすくなります。また、C#3.0ではvarキーワードを用いることで
型推論が働いてくれます。さらにカリー化を行うためのメソッドをあらかじめ拡張メソッドにしておくとより便利で、
コードが非常にスッキリします。これはカレー好きにはたまりません。


例えば、こんな感じで用意しておくと便利でしょう。

using System;

namespace ClassLibrary1
{
    public delegate TResult Func<T1, T2, T3, T4, T5, TResult>(T1 a, T2 b, T3 c, T4 d, T5 e);
    public delegate Func<T2, TResult> CurriedFunc<T1, T2, TResult>(T1 x);
    public delegate CurriedFunc<T2, T3, TResult> CurriedFunc<T1, T2, T3, TResult>(T1 x);
    public delegate CurriedFunc<T2, T3, T4, TResult> CurriedFunc<T1, T2, T3, T4, TResult>(T1 x);
    public delegate CurriedFunc<T2, T3, T4, T5, TResult> CurriedFunc<T1, T2, T3, T4, T5, TResult>(T1 x);

    public static class Extentions
    {
        public static CurriedFunc<T1, T2, TResult> Curry<T1, T2, TResult>
        (this Func<T1, T2, TResult> f)
        {
            return a => b => f(a, b);
        }

        public static CurriedFunc<T1, T2, T3, TResult> Curry<T1, T2, T3, TResult>
        (this Func<T1, T2, T3, TResult> f)
        {
            return a => b => c => f(a, b, c);
        }

        public static CurriedFunc<T1, T2, T3, T4, TResult> Curry<T1, T2, T3, T4, TResult>
        (this Func<T1, T2, T3, T4, TResult> f)
        {
            return a => b => c => d => f(a, b, c, d);
        }

        public static CurriedFunc<T1, T2, T3, T4, T5, TResult> Curry<T1, T2, T3, T4, T5, TResult>
        (this Func<T1, T2, T3, T4, T5, TResult> f)
        {
            return a => b => c => d => e => f(a, b, c, d, e);
        }
    }
}


では実際にカリー化してみましょう。

using System;
using ClassLibrary1;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            Func<decimal, decimal, decimal, decimal, decimal, decimal> f = TestMethod;
            var cf = f.Curry();
            Console.WriteLine(cf(1)(2)(3)(4)(5));
            Console.WriteLine(cf(5)(4)(3)(2)(1));
            Console.WriteLine(cf(2)(3)(4)(5)(6));
            Console.ReadLine();
        }

        public static decimal TestMethod(decimal a, decimal b, decimal c, decimal d, decimal e)
        {
            return ((a + b) * c - d) / e;
        }
    }
}


実行結果

1
25
2.5

いい感じでカリー化できていますね(^ω^)
もう型推論なしでは生きていかれないカラダになりましたw