scala – 自动散列的案例类
发布时间:2020-12-16 19:01:43 所属栏目:安全 来源:网络整理
导读:我正在寻找一种方法,让类的行为就像案例类,但这是自动的 hash consed. 实现整数列表的一种方法是: import scala.collection.mutable.{Map=MutableMap}sealed abstract class Listclass Cons(val head: Int,val tail: List) extends Listcase object Nil ext
我正在寻找一种方法,让类的行为就像案例类,但这是自动的
hash consed.
实现整数列表的一种方法是: import scala.collection.mutable.{Map=>MutableMap} sealed abstract class List class Cons(val head: Int,val tail: List) extends List case object Nil extends List object Cons { val cache : MutableMap[(Int,List),Cons] = MutableMap.empty def apply(head : Int,tail : List) = cache.getOrElse((head,tail),{ val newCons = new Cons(head,tail) cache((head,tail)) = newCons newCons }) def unapply(lst : List) : Option[(Int,List)] = { if (lst != null && lst.isInstanceOf[Cons]) { val asCons = lst.asInstanceOf[Cons] Some((asCons.head,asCons.tail)) } else None } } 而且,比如说 scala> (5 :: 4 :: scala.Nil) eq (5 :: 4 :: scala.Nil) resN: Boolean = false 我们得到 scala> Cons(5,Cons(4,Nil)) eq Cons(5,Nil)) resN: Boolean = true 现在我正在寻找的是一种通用的方法来实现这一点(或者是非常类似的).理想情况下,我不想要输入: class Cons(val head : Int,val tail : List) extends List with HashConsed2[Int,List] (或类似).有人可以拿出一些类型的系统voodoo来帮助我,还是等待宏语言可用? 解决方法
您可以为N定义几个InternableN [Arg1,Arg2,…,ResultType] traits():Internable1 [A,Z],Internable2 [A,B,Z]等等的特征定义缓存本身,我们要劫持的intern()方法和apply方法.
我们必须定义一个特征(或一个抽象类),以确保您的InternableN特征确实有一个应用方法被覆盖,让我们称之为可应用. trait Applyable1[A,Z] { def apply(a: A): Z } trait Internable1[A,Z] extends Applyable1[A,Z] { private[this] val cache = WeakHashMap[(A),Z]() private[this] def intern(args: (A))(builder: => Z) = { cache.getOrElse(args,{ val newObj = builder cache(args) = newObj newObj }) } abstract override def apply(arg: A) = { println("Internable1: hijacking apply") intern(arg) { super.apply(arg) } } } 你的类的伴侣对象必须是一个具体类实现ApplyableN与InternableN的混合.在您的随播对象中直接应用应用程序将无法正常工作. // class with one apply arg abstract class SomeClassCompanion extends Applyable1[Int,SomeClass] { def apply(value: Int): SomeClass = { println("original apply") new SomeClass(value) } } class SomeClass(val value: Int) object SomeClass extends SomeClassCompanion with Internable1[Int,SomeClass] 一件好事是,原始申请不需要修改以适应实习.它只创建实例,仅在需要创建时才调用. 整个事情可以(并且应该)也被定义为具有多个参数的类.对于双参数的情况: trait Applyable2[A,Z] { def apply(a: A,b: B): Z } trait Internable2[A,Z] extends Applyable2[A,Z] { private[this] val cache = WeakHashMap[(A,B),Z]() private[this] def intern(args: (A,B))(builder: => Z) = { cache.getOrElse(args,{ val newObj = builder cache(args) = newObj newObj }) } abstract override def apply(a: A,b: B) = { println("Internable2: hijacking apply") intern((a,b)) { super.apply(a,b) } } } // class with two apply arg abstract class AnotherClassCompanion extends Applyable2[String,String,AnotherClass] { def apply(one: String,two: String): AnotherClass = { println("original apply") new AnotherClass(one,two) } } class AnotherClass(val one: String,val two: String) object AnotherClass extends AnotherClassCompanion with Internable2[String,AnotherClass] 互动表明,Internables的apply方法在原始的apply()之前执行,只有在需要时才会被执行. scala> import SomeClass._ import SomeClass._ scala> SomeClass(1) Internable1: hijacking apply original apply res0: SomeClass = SomeClass@2e239525 scala> import AnotherClass._ import AnotherClass._ scala> AnotherClass("earthling","greetings") Internable2: hijacking apply original apply res1: AnotherClass = AnotherClass@329b5c95 scala> AnotherClass("earthling","greetings") Internable2: hijacking apply res2: AnotherClass = AnotherClass@329b5c95 我选择使用WeakHashMap,以便在其他地方不再引用interned缓存时,不会阻止垃圾收集. 代码整齐可用as a Github gist. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容