关于记忆化实施的2个问题

发布于 2024-11-05 08:53:46 字数 1534 浏览 3 评论 0原文

我有一个这样的类:

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

我想知道

1)这是否违反了短语静态类不应该有状态

2)我如何修改函数,以便它们可以接受任何函数(而不是我上面的情况,它仅适用于 F(TResult)F(T, TResult)我的意思是我可以创建另一个函数:

Function Mize(Of T, T2, TResult)(ByVal f As System.Func(Of T, T2, TResult))
                                                 As System.Func(Of T, T2, 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

听闻余生 2024-11-12 08:53:46

由于 .NET 中泛型的工作方式,不可能用任何 .NET 语言编写带有任意数量泛型参数的泛型函数。

最好的选择是:

  1. 为任意数量的参数制作代码变体,最多可达某个大值(例如 10 或 20?),就像 System.Func

  2. 使用Object作为键(使用Delegate作为函数),而不是泛型类型。这会降低类型安全性并导致速度急剧下降,只有当调用 DynamicInvoke 的成本超过函数速度时才应使用它

  3. 使用不同的语言,例如 C++、D 或 Scheme,它们支持模板(这不是一个非常简单的选择,但我还是提到了)。

    例如,在某些语言中记忆很容易,例如 D:

    自动记忆(别名 F、T...)(T args)
    {
        自动键=元组(args); //将args打包成一个
        静态 typeof(F(args))[typeof(key)] 缓存; //字典
        返回缓存中的密钥?缓存[键] : (缓存[键] = F(args));
    }
    

    可以很容易地使用,例如:

    结果 = memoize!(func)(args); //使用参数调用记忆的“func”
    

不,您的示例不会违反状态原则,因为您的静态类保存状态! (您实际上每次都捕获一个局部变量,而不是重用以前的任何内容。)不过,我的确实如此。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文