I've got a couple of utility functions to support memoization for functions with anywhere between 0 to 8 arguments:
Public Shared Function Mize(Of TResult)(ByVal input_f As System.Func(Of TResult)) As System.Func(Of TResult)
Dim is_new = True
Dim result As TResult
Return Function()
If is_new Then
result = input_f()
is_new = False
End If
Return result
End Function
End Function
Public Shared Function Mize(Of TArg1 As Structure, TResult)(ByVal input_f As System.Func(Of TArg1, TResult)) As System.Func(Of TArg1, TResult)
Dim map = New System.Collections.Generic.Dictionary(Of TArg1, TResult)
Return Function(arg1 As TArg1)
Dim result As TResult
If map.TryGetValue(arg1, result) Then Return result
result = input_f(arg1)
map.Add(arg1, result)
Return result
End Function
End Function
Public Shared Function Mize(Of TArg1 As Structure, TArg2 As Structure, TResult)(ByVal input_f As System.Func(Of TArg1, TArg2, TResult)) As System.Func(Of TArg1, TArg2, TResult)
Dim map = New System.Collections.Generic.Dictionary(Of System.Tuple(Of TArg1, TArg2), TResult)
Return Function(arg1 As TArg1, arg2 As TArg2)
Dim args = System.Tuple.Create(arg1, arg2)
Dim result As TResult
If map.TryGetValue(args, result) Then Return result
result = input_f(arg1, arg2)
map.Add(args, result)
Return result
End Function
End Function
Public Shared Function Mize(Of TArg1 As Structure, TArg2 As Structure, TArg3 As Structure, TResult)(ByVal input_f As System.Func(Of TArg1, TArg2, TArg3, TResult)) As System.Func(Of TArg1, TArg2, TArg3, TResult)
Dim map = New System.Collections.Generic.Dictionary(Of System.Tuple(Of TArg1, TArg2, TArg3), TResult)
Return Function(arg1 As TArg1, arg2 As TArg2, arg3 As TArg3)
Dim args = System.Tuple.Create(arg1, arg2, arg3)
Dim result As TResult
If map.TryGetValue(args, result) Then Return result
result = input_f(arg1, arg2, arg3)
map.Add(args, result)
Return result
End Function
End Function
Public Shared Function Mize(Of TArg1 As Structure, TArg2 As Structure, TArg3 As Structure, TArg4 As Structure, TResult)(ByVal input_f As System.Func(Of TArg1, TArg2, TArg3, TArg4, TResult)) As System.Func(Of TArg1, TArg2, TArg3, TArg4, TResult)
Dim map = New System.Collections.Generic.Dictionary(Of System.Tuple(Of TArg1, TArg2, TArg3, TArg4), TResult)
Return Function(arg1 As TArg1, arg2 As TArg2, arg3 As TArg3, arg4 As TArg4)
Dim args = System.Tuple.Create(arg1, arg2, arg3, arg4)
Dim result As TResult
If map.TryGetValue(args, result) Then Return result
result = input_f(arg1, arg2, arg3, arg4)
map.Add(args, result)
Return result
End Function
End Function
Public Shared Function Mize(Of TArg1 As Structure, TArg2 As Structure, TArg3 As Structure, TArg4 As Structure, TArg5 As Structure, TResult)(ByVal input_f As System.Func(Of TArg1, TArg2, TArg3, TArg4, TArg5, TResult)) As System.Func(Of TArg1, TArg2, TArg3, TArg4, TArg5, TResult)
Dim map = New System.Collections.Generic.Dictionary(Of System.Tuple(Of TArg1, TArg2, TArg3, TArg4, TArg5), TResult)
Return Function(arg1 As TArg1, arg2 As TArg2, arg3 As TArg3, arg4 As TArg4, arg5 As TArg5)
Dim args = System.Tuple.Create(arg1, arg2, arg3, arg4, arg5)
Dim result As TResult
If map.TryGetValue(args, result) Then Return result
result = input_f(arg1, arg2, arg3, arg4, arg5)
map.Add(args, result)
Return result
End Function
End Function
Public Shared Function Mize(Of TArg1 As Structure, TArg2 As Structure, TArg3 As Structure, TArg4 As Structure, TArg5 As Structure, TArg6 As Structure, TResult)(ByVal input_f As System.Func(Of TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TResult)) As System.Func(Of TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TResult)
Dim map = New System.Collections.Generic.Dictionary(Of System.Tuple(Of TArg1, TArg2, TArg3, TArg4, TArg5, TArg6), TResult)
Return Function(arg1 As TArg1, arg2 As TArg2, arg3 As TArg3, arg4 As TArg4, arg5 As TArg5, arg6 As TArg6)
Dim args = System.Tuple.Create(arg1, arg2, arg3, arg4, arg5, arg6)
Dim result As TResult
If map.TryGetValue(args, result) Then Return result
result = input_f(arg1, arg2, arg3, arg4, arg5, arg6)
map.Add(args, result)
Return result
End Function
End Function
Public Shared Function Mize(Of TArg1 As Structure, TArg2 As Structure, TArg3 As Structure, TArg4 As Structure, TArg5 As Structure, TArg6 As Structure, targ7 As Structure, TResult)(ByVal input_f As System.Func(Of TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, targ7, TResult)) As System.Func(Of TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, targ7, TResult)
Dim map = New System.Collections.Generic.Dictionary(Of System.Tuple(Of TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, targ7), TResult)
Return Function(arg1 As TArg1, arg2 As TArg2, arg3 As TArg3, arg4 As TArg4, arg5 As TArg5, arg6 As TArg6, arg7 As targ7)
Dim args = System.Tuple.Create(arg1, arg2, arg3, arg4, arg5, arg6, arg7)
Dim result As TResult
If map.TryGetValue(args, result) Then Return result
result = input_f(arg1, arg2, arg3, arg4, arg5, arg6, arg7)
map.Add(args, result)
Return result
End Function
End Function
Public Shared Function Mize(Of TArg1 As Structure, TArg2 As Structure, TArg3 As Structure, TArg4 As Structure, TArg5 As Structure, TArg6 As Structure, targ7 As Structure, targ8 As Structure, TResult)(ByVal input_f As System.Func(Of TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, targ7, targ8, TResult)) As System.Func(Of TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, targ7, targ8, TResult)
Dim map = New System.Collections.Generic.Dictionary(Of System.Tuple(Of TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, targ7, targ8), TResult)
Return Function(arg1 As TArg1, arg2 As TArg2, arg3 As TArg3, arg4 As TArg4, arg5 As TArg5, arg6 As TArg6, arg7 As targ7, arg8 As targ8)
Dim args = New System.Tuple(Of TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, targ7, targ8)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
Dim result As TResult
If map.TryGetValue(args, result) Then Return result
result = input_f(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
map.Add(args, result)
Return result
End Function
End Function
The problem is that the memoization algorithm is repeated 6 times (the functions that accept functions with 2 arguments to 8 arguments basically have the same algorithm).
I'm clearly violating DRY here, and I want to modify the code above to not violate DRY.
I've tried shifting those repeating algorithm into a separate function, but since VB.NET/C# does not allow System.Delegate
as a generic constraint, I'm out of ideas as to how I would do it.
What should I do and how can I improve my code above?