Created
June 6, 2014 08:23
-
-
Save wgross/7470ace5904326b15b51 to your computer and use it in GitHub Desktop.
Memoization of delegates calculation result using strong or weak references. Extension to multiple parameters with partial application. The memoization container can be changed by implementing a custom memoization container factory.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
namespace Memoization | |
{ | |
public static class Memoize | |
{ | |
#region Create memoization containers | |
public interface IContainerFactory | |
{ | |
IDictionary<K, V> CreateNew<K, V>(IEqualityComparer<K> withEqualityComparer = null); | |
} | |
private class ContainerAsDictionaryFactory : IContainerFactory | |
{ | |
public IDictionary<K, V> CreateNew<K, V>(IEqualityComparer<K> withEqualityComparer = null) | |
{ | |
return new Dictionary<K, V>(withEqualityComparer ?? EqualityComparer<K>.Default); | |
} | |
} | |
public static readonly IContainerFactory ContainerAsDictionary = new ContainerAsDictionaryFactory(); | |
#endregion Create memoization containers | |
#region Partial memoization results to delegates by using partial application: The function returns a function receiving one parameter less | |
public class Partial | |
{ | |
public static Func<P1, Func<P2, Func<P3, R>>> Strong<P1, P2, P3, R>(Func<P1, P2, P3, R> toMemoize, IContainerFactory useContainerFactory = null) | |
{ | |
return Memoize.Strong<P1, Func<P2, Func<P3, R>>>((p1) => Memoize.Partial.Strong<P2, P3, R>((p2, p3) => toMemoize(p1, p2, p3), useContainerFactory), useContainerFactory); | |
} | |
public static Func<P1, Func<P2, R>> Strong<P1, P2, R>(Func<P1, P2, R> toMemoize, IContainerFactory useContainerFactory = null) | |
{ | |
return Memoize.Strong<P1, Func<P2, R>>((p1) => Memoize.Strong<P2, R>(p2 => toMemoize(p1, p2), useContainerFactory), useContainerFactory); | |
} | |
} | |
#endregion Partial memoization results to delegates by using partial application: The function returns a function receiving one parameter less | |
#region Full memoization results to delegates receiving the same number of parameters as the memoized function | |
public class Full | |
{ | |
public static Func<P1, P2, P3, R> Strong<P1, P2, P3, R>(Func<P1, P2, P3, R> toMemoize, IContainerFactory useContainerFactory = null) | |
{ | |
var tmp = Partial.Strong<P1, P2, P3, R>(toMemoize, useContainerFactory); | |
return (p1, p2, p3) => tmp(p1)(p2)(p3); | |
} | |
public static Func<P1, P2, R> Strong<P1, P2, R>(Func<P1, P2, R> toMemoize, IContainerFactory useContainerFactory = null) | |
{ | |
var tmp = Partial.Strong<P1, P2, R>(toMemoize, useContainerFactory); | |
return (p1, p2) => tmp(p1)(p2); | |
} | |
} | |
#endregion Full memoization results to delegates receiving the same number of parameters as the memoized function | |
#region Base memoization factory method: No separation of partial application and full memoization for one parameter | |
public static Func<P, R> Strong<P, R>(this Func<P, R> toMemoize, IContainerFactory useContainerFactory = null) | |
{ | |
var tmp = (useContainerFactory ?? ContainerAsDictionary).CreateNew<P, R>(); | |
return p => | |
{ | |
R value; | |
if (!tmp.TryGetValue(p, out value)) | |
{ | |
value = toMemoize(p); | |
tmp.Add(p, value); | |
} | |
return value; | |
}; | |
} | |
public static Func<P, R> Weak<P, R>(Func<P, R> toMemoize, IContainerFactory useContainerFactory = null) | |
where R : class | |
{ | |
var tmp = (useContainerFactory ?? ContainerAsDictionary).CreateNew<P, WeakReference<R>>(); | |
return p => | |
{ | |
WeakReference<R> weakReference; | |
R weakTarget; | |
if (!tmp.TryGetValue(p, out weakReference) || !weakReference.TryGetTarget(out weakTarget)) | |
{ | |
weakTarget = toMemoize(p); | |
weakReference = new WeakReference<R>(weakTarget); | |
tmp.Add(p, weakReference); | |
} | |
return weakTarget; | |
}; | |
} | |
#endregion Base memoization factory method: No separation of partial application and full memoization for one parameter | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment