【问题标题】:Pattern matching tuple elements of equal types相同类型的模式匹配元组元素
【发布时间】:2020-09-04 04:51:26
【问题描述】:

我正在对两个对象的元组进行模式匹配,并希望匹配所有 object1object2 类型相同的情况,类似于

(object1, object2) match {
    case (o1: T, o2: T) =>
      // Ignore same objects case
    case
    .
    .
    .
    case (_, _)
      // Here I can be certain that the two object are not of the same type
  

【问题讨论】:

  • case (o1, o2) if (o1 == 02) => 另外,请不要进行类型检查 case foo: T 由于擦除通常是不安全的,并且通常是代码异味。
  • @LuisMiguelMejíaSuárez 谢谢!我怎么没想到?你说我不应该使用 case a: String 或 b: Int 之类的东西?你能解释一下为什么吗?
  • @LuisMiguelMejíaSuárez 你检查元组元素是否相等或类型相同?
  • @DmytroMitin 实际上我正在匹配 case 对象,所以这很好用,但如果有一个解决方案也可以检查相等类型,我不介意知道它 :)
  • @DmytroMitin Liskov 是子类型化的原则。用子类型打破任何语言的 Liskov 是 "sin" :p

标签: scala pattern-matching


【解决方案1】:

试试

def test(object1: Any, object2: Any) = (object1, object2) match {
  case (o1, o2) if o1.getClass == o2.getClass => println("same")
  case (_, _) => println("different")
}

test(1, 2) //same
test(1, "2") //different
test(1: Any, "2": Any) //different
test(Some(1), Some("2")) //same

import scala.reflect.runtime.universe._
def getType[T: TypeTag](t: T): Type = typeOf[T]

def test[A: TypeTag, B: TypeTag](object1: A, object2: B) = (object1, object2) match {
  case (o1, o2) if getType(o1) == getType(o2) => println("same")
  case (_, _) => println("different")
}

test(1, 2) //same
test(1, "2") //different
test(1: Any, "2": Any) //same
test(Some(1), Some("2")) //different

def test[A, B](object1: A, object2: B)(implicit ev: A =:= B) = println("same")

test(1, 2) //compiles
// test(1, "2") //doesn't compile
test(1: Any, "2": Any) //compiles
// test(Some(1), Some("2")) //doesn't compile

如果object1object2 实际上是(案例)对象,那么最简单的是

def test(object1: A, object2: A) = (object1, object2) match {
  case (o1, o2) if o1 == o2 => println("same")
  case (_, _) => println("different")
}

sealed trait A
case object B extends A
case object C extends A

test(B, B) //same
test(B, C) //different

【讨论】:

    【解决方案2】:

    @Dmytro 答案的另一个变体: 你可以用ClassTag代替TypeTag

    import scala.reflect.ClassTag
    def test[A: ClassTag, B: ClassTag](object1: A, object2: B): Unit =
      (object1, object2) match {
        case (_: A, _: A) => println("same")
        case (_, _)       => println("different")
      }
    
    test(1, 11)   // same
    test(1, "11") // different
    

    【讨论】:

    • 我的回答中的行为与所有test不同:test(1, 2)test(1, "2")test(1: Any, "2": Any)test(Some(1), Some("2"))生产samedifferentsamesames>
    • Option 不是高级别的。仅仅因为某事物具有类型参数并不意味着它一定是更高种类的。
    • @SethTisue 这是标准争议(“高”是从2还是1开始)stackoverflow.com/questions/6246719/…
    • @PritamKadam 顺便说一句,因为你只使用A 来匹配B 的上下文绑定的模式是不必要的:def test[A: ClassTag, B](object1: A, object2: B): Unit = ...
    猜你喜欢
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多