/// <summary> /// Returns a Func<T,R> that wraps func. Each time the resulting /// Func<T,R> is called with a new value, its result is memoized (cached). /// Subsequent calls use the memoized value. /// /// Remarks: /// Thread-safe and memory-leak safe. /// </summary> public static Func <T, R> memo <T, R>(Func <T, R> func) { var cache = new WeakDict <T, R>(); var syncMap = new ConcurrentDictionary <T, object>(); return(inp => matchUnsafe(cache.TryGetValue(inp), Some: x => x, None: () => { R res; var sync = syncMap.GetOrAdd(inp, new object()); lock (sync) { res = cache.GetOrAdd(inp, func); } syncMap.TryRemove(inp, out sync); return res; })); }
/// <summary> /// Returns a `Func<A, B>` that wraps func. Each time the resulting /// `Func<A, B>` is called with a new value, its result is memoized (cached). /// Subsequent calls use the memoized value. /// /// Remarks: /// Thread-safe and memory-leak safe. /// </summary> public static Func <A, B> memo <A, B>(Func <A, B> func) { var cache = new WeakDict <A, B> (); var syncMap = new ConcurrentDictionary <A, object>(); return(inp => { if (cache.TryGetValue(inp, out var x)) { return x; } else { B res; var sync = syncMap.GetOrAdd(inp, new object()); lock (sync) { res = cache.GetOrAdd(inp, func); } syncMap.TryRemove(inp, out sync); return res; } }); }