gpt4 book ai didi

集合中的 Scala 案例类

转载 作者:行者123 更新时间:2023-12-04 14:52:53 24 4
gpt4 key购买 nike

场景:例如,我正在解析一个 IL,并希望从基于堆栈的表示转换为 CFG。

我的 IL 由多个操作组成,如 PushInt(value)、Pop 等。现在的问题是,就 Scala 而言,哪种实现是正确的。我很想使用案例类/对象或提取器,以便我可以编写代码

op match {
case PushInt(x) => doSomethingWith x
case Pop => ...
}

现在问题存在于类似 PushInt(1) :: PushInt(1) :: Pop :: Pop 的序列中。由于 PushInt(1) 等于 PushInt(1) 并且我无法将多个(相等)操作添加到集合中。但是我知道我正在丢弃一些信息,即流中的位置,但这被隐式存储为序列中的 te 索引。
  • 一种可能的解决方案是覆盖 hashCode 方法并打破 equal/hashCode 的规则。我对此并不满意。
  • 另一种选择是将“创建时间”计数器存储在抽象库中,以便 case class PushInt(value: Int) extends AbstractOp(AbstractOp.nextIndex)
  • 使用提取器,但在这种情况下,我会错过一些不错的功能,例如 hashCode、equals、toString 的实现,更重要的是检查彻底匹配。

  • 所以我现在的问题是如何根据我的要求对我的结构进行建模。就 Scala 而言,任何可能的解决方案是否“正确”?

    最佳答案

    首先,让我们解决找到您想要的确切实例的问题:

    scala> trait AbstractOp
    defined trait AbstractOp

    scala> case class Pop() extends AbstractOp {
    | override def equals(other: Any) = other match {
    | case that: Pop => this eq that
    | case _ => false
    | }
    | }
    defined class Pop

    scala> case class PushInt(val i: Int) extends AbstractOp {
    | override def equals(other: Any) = other match {
    | case that: PushInt => this eq that
    | case _ => false
    | }
    | }
    defined class PushInt

    scala> val l = List(PushInt(1), PushInt(1), Pop(), Pop())
    l: List[Product with AbstractOp] = List(PushInt(1), PushInt(1), Pop(), Pop())

    scala> val op = l(1)
    op: Product with AbstractOp = PushInt(1)

    scala> println( l.indexOf( op ) )
    1

    当然,这意味着 PushInt(1) != PushInt(1) , 除非它是 PushInt(1) 的完全相同的实例.它不会坏 equals/ hashCode契约(Contract)因为 a.equals(b) => a.hashCode == b.hashCode ,但是 a.hashCode == b.hashCode不代表什么。但是如果你唯一的用途是找到那个实例,试试这个:
    scala> case class Pop() extends AbstractOp
    defined class Pop

    scala> case class PushInt(val i: Int) extends AbstractOp
    defined class PushInt

    scala> val l = List(PushInt(1), PushInt(1), Pop(), Pop())
    l: List[Product with AbstractOp] = List(PushInt(1), PushInt(1), Pop(), Pop())

    scala> val op = l(1)
    op: Product with AbstractOp = PushInt(1)

    scala> println( l.findIndexOf( op eq _ ) )
    1

    无论哪种方式,如果您在列表中重新插入该实例,您都会遇到麻烦。您必须确保您插入的每个实例都是唯一的。您甚至可以编写自己的集合,或者在插入重复实例时抛出异常,或者复制传递给它的任何实例(使用 Scala 2.8 上的案例类和 copy 方法很容易)。

    关于集合中的 Scala 案例类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1917856/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com