Monday 24 June 2013

Anonymous function in anger with Memoize

About a year ago I blogged about anonymous functions, lambdas and delegates. I've had cause to use these principals in anger to create a memoize function; not exactly original but interesting never the less. I made this memoize function, which takes an anonynous function that takes 2 parameters.

static Func<T1, T2, TResult> Memoize<T1, T2, TResult>(Func<T1, T2, TResult> f)
{
    var dict = new Dictionary<Tuple<T1, T2>, TResult>();
    return (a, b) =>
    {
        TResult result;
        if (!dict.TryGetValue(Tuple.Create(a, b), out result))
        {
            result = f(a, b);
            dict.Add(Tuple.Create(a, b), result);
        }
        return result;
    };
}

N.B. It uses the .net4 Tuple class to store the 2 parameters, for the sake a simplicity I haven't generalized this for 1 or > 2 parameters, or made it an extension method. You then need to wrap the function you want memoizing.

var myFunc1 = Memoize((Func<int, int, MyClass1>)Some.Dot.Namespace.Func1);
var myNewClass = new MySomethingClass();
var myFunc2 = Memoize((Func<string, string, MyClass2>)myNewClass.Func2);

while(true)
{
    var result = myFunc1(1,2);
    var result2 = myFunc2("1","2");
}

The results of the memoized functions are cached inside the function calls, leading to better performance if the function is a called with the same parameters many times in the loop.