Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
缓存Scala案例类实例_Scala_Caching_Case Class - Fatal编程技术网

缓存Scala案例类实例

缓存Scala案例类实例,scala,caching,case-class,Scala,Caching,Case Class,假设我们有以下案例类: abstract sealed class Tree case class Leaf(i: Int) extends Tree case class Node(left: Tree, right: Tree) extends Tree 每次调用case类构造函数时,都会在内存中创建一个新对象。例如,在下面的代码中: val a = Leaf(0) val b = Leaf(0) a和b指向内存中不同的对象: a == b // true a eq b // fals

假设我们有以下案例类:

abstract sealed class Tree
case class Leaf(i: Int) extends Tree
case class Node(left: Tree, right: Tree) extends Tree
每次调用case类构造函数时,都会在内存中创建一个新对象。例如,在下面的代码中:

val a = Leaf(0)
val b = Leaf(0) 
a和b指向内存中不同的对象:

a == b // true
a eq b // false
我想重写case类的“apply”方法,使它们返回一个缓存对象(如果它已经存在),这样,在上面的最小示例中,“aeq b”将返回true

我在Stackoverflow中找到了这两个相关的答案:

  • (显示如何重写“应用”方法)

  • (显示缓存案例类实例的简单方法)

我计划以一种结合上述两种方法的方式,使用缓存实现我的覆盖“apply”方法。但我想知道是否有其他的方式我应该考虑。如果你知道,请在这里分享你的解决方案好吗

缓存case类的实例似乎是减少内存消耗的一件非常有用和自然的事情。然而,我计划实现的解决方案(基于上面链接的两个答案)似乎非常复杂,需要大量样板代码,这将损害案例类的优雅性和简洁性。有人知道Scala语言的未来版本是否允许我们通过编写以下简单内容来实现case类实例缓存:

abstract sealed class Tree
cached case class Leaf(i: Int) extends Tree
cached case class Node(left: Tree, right: Tree) extends Tree
?

缓存case类的实例似乎是减少内存消耗的一件非常有用和自然的事情

请注意,这甚至不是一个自动的改进,这在很大程度上取决于case类的使用模式(不仅是您的,还取决于使用您的库的任何人):

  • 您需要考虑内存缓存需求以及无法对缓存引用的实例进行垃圾收集(请注意,使用
    WeakHashMap
    不会有帮助:它要求“值对象不直接或间接地强烈引用它们自己的键”)

  • 如果键是原语(如
    Leaf
    ),则在查找之前需要对它们进行装箱,这通常已经是一个构造函数调用

  • 在映射中查找要比普通构造函数调用慢得多

  • 转义分析通常会确保对象不是实际构造的,同时确保程序的工作方式与实际一样。当然,缓存将确保对象不会转义


  • 但是忽略所有这些,您可以编写一个宏注释,它将允许
    @cached-case-class-Leaf(i:Int)扩展树
    ,并生成所需的代码(或者至少
    @cached-case-class
    ;我不确定您是否能够覆盖
    apply
    )。由于上述原因,我不希望它很快成为该语言的一部分。

    这只是一个随机的问题,您是否见过这种“缓存”作为其他语言的核心功能?至少我还没有遇到它,我也是。这让我想知道是否有这样的原因@Alexey Romanov在下面的回答中指出了一些有趣的原因。总的来说,这些都是好的方面,尽管其中一些不适用于我的特定使用模式。你能详细说明你的第四点吗?我如何知道何时不会构造新对象?我在哪里可以了解更多信息?您能提供一个@cachedcase宏注释的最小示例吗?有关基本解释,请参阅。其思想是,如果一个对象只在一个方法中使用,而没有“转义”,那么可以通过用局部变量替换所有字段来消除它。但检查是否消除了任何特定的分配绝非易事(而且无论如何都需要JIT来启动,所以尝试一次是行不通的)。请参见例如,
    @cachedcase
    示例,您指的是使用还是实现?用法将是
    @cachedcase类叶(i:Int)扩展树
    。实施将需要我目前没有的时间,尤其是要把它做好。谢谢。我指的是实现,而不是使用。但别担心。