Служебные функции для обслуживания мемоизация функций


У меня есть пара полезных функций для поддержки мемоизация функций в пределах от 0 до 8 аргументов:

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

Проблема в том, что алгоритм мемоизация повторяется 6 раз (в функции, которые принимают функции с 2 аргументами к 8 аргументов в основном имеют один и тот же алгоритм).

Я явно нарушая сухой здесь, и я хочу модифицировать код выше, чтобы не нарушать сухой.

Я пробовал перенося те повторяют алгоритм в отдельную функцию, но с VB.NET/C# не позволяет система.Делегировать в качестве универсального ограничения, я выхожу из идеи о том, как я бы сделал это.

Что мне делать и как я могу улучшить мой код выше?



Комментарии
1 ответ

Если вы не хотите, чтобы пойти с другим подходом, как инъекции кодекса (см. комментарий Антона), вы застряли в значительной степени с этим. Я согласен, это некрасиво и повторяющиеся. В основном вы сталкивались с края системы типа. Параметры типа немного как параметры метода, и аргументы типа мало, как передача аргументов в метод, а методы являются гораздо более гибким. Методы разрешения всевозможных высших порядков программирования, методов может быть вариативной, и так далее. Нет вариативную универсальные типы в рамках .Чистый тип системы, который является действительно, что вы хотите сделать такого рода вещи работать гладко.

Что касается нарушения принципа DRY, не беспокойся об этом. Причина, чтобы не повторять самого себя, потому что если у вас есть такой же кусок сложную бизнес-логику в двух разных местах, и один из них нуждается в установке, они могут легко выйти из синхронизации, когда вы забыли исправить другой. (Компилятор C# кода изобилует комментариями, которые говорят: "Если вы измените ссылку типа конвертируемости алгоритм здесь, не забудьте также изменить его здесь, здесь и здесь..."), что вы строите вот такой механизм: скучная водопроводным код, который делает логику программы более эффективным. Сухая больше подходит для бизнес-логики, чем скучные механизмы.

14
ответ дан 19 мая 2011 в 02:05 Источник Поделиться