Commits

Devin Martin committed e440b7d

Add a memoize compositional function

Comments (0)

Files changed (4)

FlipSideOut.Linqpad.Tests/FlipSideOut.Linqpad.Tests.csproj

     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="FunctionalTests.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="StatisticalExtensionsTests.cs" />
   </ItemGroup>

FlipSideOut.Linqpad.Tests/FunctionalTests.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using FluentAssertions;
+using NUnit.Framework;
+
+namespace FlipSideOut.Linqpad.Tests
+{
+    [TestFixture]
+    public class FunctionalTests
+    {
+        [Test]
+        public void OnlyRunOncePerInput()
+        {
+            int invocationCount = 0;
+            Func<int, int> countAction = (i) =>
+            {
+                invocationCount++;
+                return i + 1;
+            };
+
+            var memoizedCountAction = Functional.Memoize(countAction);
+
+            memoizedCountAction(1).Should().Be(2);
+            invocationCount.Should().Be(1);
+            memoizedCountAction(1).Should().Be(2);
+            invocationCount.Should().Be(1);
+
+            memoizedCountAction(2).Should().Be(3);
+            invocationCount.Should().Be(2);
+        }
+    }
+}

FlipSideOut.Linqpad/FlipSideOut.Linqpad.csproj

     <Compile Include="EnumerableExtensions.cs" />
     <Compile Include="FluentMathExtensions.cs" />
     <Compile Include="FluentRangeExtensions.cs" />
+    <Compile Include="Functional.cs" />
     <Compile Include="Histogram.cs" />
     <Compile Include="Quantile.cs" />
     <Compile Include="RandomEnumerables.cs" />

FlipSideOut.Linqpad/Functional.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FlipSideOut.Linqpad
+{
+    public class Functional
+    {
+        public static Func<TInput, TReturn> Memoize<TInput, TReturn>(Func<TInput, TReturn> f)
+        {
+            var map = new Dictionary<TInput, TReturn>();
+            return a =>
+            {
+                TReturn value;
+                if (map.TryGetValue(a, out value))
+                    return value;
+                value = f(a);
+                map.Add(a, value);
+                return value;
+            };
+        }
+    }
+}