scala - 在子类中扩展 Scala 模式匹配,同时保持复杂性

标签 scala pattern-matching complexity-theory

我有一个 Scala 问题。想象一下您正在构建代码来处理不同的操作,即

operation match {
   case A => doA()
   case B => doB()
   case _ => throw new Exception("Unknown op: " + operation)
}

现在,想象一下,稍后您想要构建一个新版本,并且想要扩展操作 C 的模式匹配。如何才能以这样的方式实现操作分辨率仍为 O(1)?

我的意思是,我可以修改上面的代码来执行以下操作:

   case _ => handleUnknownOperation(operation)

子类可以实现handleUnknownOperation来执行以下操作:

operation match {
   case C => doC()
}

但这很糟糕,因为这意味着 C 操作需要 O(2)。

扩展这种模式匹配结构的任何其他想法或最佳实践?

干杯, 加尔德

最佳答案

为了回答最初的问题,模式匹配被有效地转换为一系列 if/else 语句,只是一系列测试。最后的 case _ 只是一个失败(没有关联的测试)。因此,在一场比赛中拥有 A、B 和 C 以及一场比赛中存在 A 和 B 然后委托(delegate)给另一场与 C 匹配的比赛之间没有什么区别。以下为例:

class T

case class A(v: Int) extends T
case class B(v: Int) extends T
case class C(v: Int) extends T

class Foo {
  def getOperation(t: T): Unit = {
    t match {
      case A(2) => println("A")
      case B(i) => println("B")
      case _ => unknownOperation(t)
    }
  }

  def unknownOperation(t: T): Unit = println("unknown operation t=" + t)
}

class Bar extends Foo {
  override def unknownOperation(t: T): Unit = t match {
    case C(i) => println("C")
    case _ => println("unknown operation t=" + t)
  }
}

使用jad反编译Foo.class,得到:

public void getOperation(T t) {
label0:
    {
        T t1 = t;
        if(t1 instanceof A)
        {
            if(((A)t1).v() == 2)
            {
                Predef$.MODULE$.println("A");
                break label0;
            }
        } else
        if(t1 instanceof B)
        {
            Predef$.MODULE$.println("B");
            break label0;
        }
        unknownOperation(t);
    }
}

所以,我想说你不应该担心性能[*]。

但是,从设计的角度来看,我可能会稍微改变一下,或者像 Frank 建议的那样使用命令模式,或者不重写子类中的 unknownOperation ,您可以重写 getOperation,它与 C 进行匹配,然后委托(delegate)给 super.getOperation(),这对我来说似乎更简洁。

class Bar extends Foo {
  override def getOperation(t: T): Unit = t match {
    case C(i) => println("C")
    case _ => super.getOperation(t)
  }
}

[*] 需要注意的是复杂性。 Scala 2.10 之前的版本存在一个问题,其中模式匹配器生成的 .class 文件过于复杂 ( nested extractors generate exponential-space bytecode ),因此如果您使用的匹配非常复杂,这可能会导致问题。这个问题在 2.10 中通过虚拟模式匹配器得到了修复。如果您遇到此问题,那么解决此错误的方法之一是将模式匹配拆分为不同的方法/类。

关于scala - 在子类中扩展 Scala 模式匹配,同时保持复杂性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9194428/

相关文章:

scala - 似乎无法让Future在Scala中运行回调

ios - 用于匹配字符串中数字的小数部分并修改它的 Swift 正则表达式

algorithm - 寻找主定理的 lambda

c# - 函数的复杂性和算法

haskell - : Option{. 形式的模式匹配 .} <-

python - 线性时间与时间二次时间

java - 有没有办法在运行时重命名 Scala(或 Java)中的方法?

scala - 如何在不导致重新编译的情况下更改 sbt 项目的编译器标志?

scala - Spark 结构化流 - 将静态数据集与流数据集连接起来

scala - 模式匹配和类型系统有什么关系?