开发者

2 questions regarding implementation of memoization

开发者 https://www.devze.com 2023-03-03 21:06 出处:网络
I\'ve got a class like this: Public NotInheritable Class F Private Sub New() End Sub Public Shared Function Mize(Of TResult)(ByVal f As System.Func(Of TResult)) As System.Func(Of TResult)

I've got a class like this:

Public NotInheritable Class F
    Private Sub New()
    End Sub
    Public Shared Function Mize(Of TResult)(ByVal 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 = f()
                   End If
                   Return result
               End Function
    End Function
    Public Shared Function Mize(Of T, TResult)(ByVal f As System.Func(Of T, TResult)) As System.Func(Of T, TResult)
        Dim is_new_s = New System开发者_开发知识库.Collections.Generic.List(Of Boolean)
        Dim inputs = New System.Collections.Generic.List(Of T)
        Dim d = New System.Collections.Generic.Dictionary(Of T, TResult)

        Return Function(arg1 As T)
                   If d.ContainsKey(arg1) Then
                       Return d.Item(arg1)
                   Else
                       Dim result = f(arg1)
                       d.Add(arg1, result)
                       Return result
                   End If
               End Function
    End Function End Class

and I'm wondering

1) Is this violating the phrase static classes should not have state?

2) How can I modify the functions such that they can accept any function (instead of my above situation which only works with F(TResult) and F(T, TResult). I mean i can create another function that is:

Function Mize(Of T, T2, TResult)(ByVal f As System.Func(Of T, T2, TResult))
                                                 As System.Func(Of T, T2, TResult)

and so on but obviously it doesn't scale very well at all.


It's not possible to write a generic function in any .NET language that takes an arbitrary number of generic parameters, because of the way generics work in .NET.

Your best bet is to either:

  1. Make variants of your code for any number of parameters up to something large (like 10 or 20?), just like System.Func<TResult, T1, T2, T3, ...> does.

  2. Use Objects as keys (and Delegates as functions), instead of generic types. This will reduce type safety and can cause dramatic slowdowns, and you should only use it if the cost of calling DynamicInvoke is outweighed by the speed of your function.

  3. Use a different language, like C++, D, or Scheme, which supports templates (not a very easy option but I mentioned it anyway).

    e.g. memoization is easy in some languages, like D:

    auto memoize(alias F, T...)(T args)
    {
        auto key = tuple(args); //Pack args into one
        static typeof(F(args))[typeof(key)] cache; //Dictionary
        return key in cache ? cache[key] : (cache[key] = F(args));
    }
    

    which can be easily used like:

    result = memoize!(func)(args);  //Calls a memoized 'func' with args
    

And no, your example doesn't violate the state principle because your static class doesn't hold state! (You're really capturing a local variable every time, not reusing anything from before.) Mine does, though.

0

精彩评论

暂无评论...
验证码 换一张
取 消