Skip to content

Instantly share code, notes, and snippets.

@mjgoeke
Created December 25, 2020 08:21
Show Gist options
  • Save mjgoeke/1c5a5d28f0580946be7942e7a899c3e3 to your computer and use it in GitHub Desktop.
Save mjgoeke/1c5a5d28f0580946be7942e7a899c3e3 to your computer and use it in GitHub Desktop.
C# memoize higher order functions by using tuples
using System;
using System.Collections.Concurrent;
namespace ns
{
//even though this looks like it only takes functions with one input
// by using C# tuple types, one can have any number of inputs (or outputs)
// see example below
public class Memoized<T, TResult>
{
public Memoized(Func<T, TResult> func) => _func = func;
private readonly Func<T, TResult> _func;
private readonly ConcurrentDictionary<T,TResult> _cache = new ConcurrentDictionary<T, TResult>();
public TResult Get(T input) => _cache.GetOrAdd(input, _func);
}
public static class MemoizedExtensions
{
public static Func<T, TResult> Memoize<T, TResult>(this Func<T, TResult> func) => new Memoized<T, TResult>(func).Get;
}
class Program
{
static void Main()
{
var fun = new Func<(double x, double y , double z), (double x, double y, double z)>(inverse).Memoize();
Console.WriteLine("fun: " + fun((1.1, 2.1, 3.1))); // will WriteLine in 'inverse' function the first time
Console.WriteLine("fun: " + fun((1.1, 2.1, 3.1))); // will directly return result after called once
Console.WriteLine("fun: " + fun((1.1, 2.1, 3.1)));
}
static (double x, double y, double z) inverse((double x, double y, double z) vec)
{
var (x, y, z) = vec;
Console.WriteLine(string.Format("{0} called ({1}, {2}, {3})", nameof(inverse), x, y, z));
return (-x, -y, -z);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment