代码之家  ›  专栏  ›  技术社区  ›  Sebastian Celestino

如何使用延迟初始化对元组进行模式匹配?

  •  3
  • Sebastian Celestino  · 技术社区  · 6 年前

    我有一个场景,我需要调用多达三个服务来做一些事情。每个服务都有某种优先级,我的算法取决于每个服务结果的组合(所有服务,两个甚至一个)。为了处理这种情况,我想使用模式匹配(因为匹配和变量提取)

    这是一个简单的例子。

    case class Foo(bar: String, baz: Option[String])
    
    def expensiveOperation1(): String = ???
    def expensiveOperation2(): List[Int] = ???
    def expensiveOperation3(): Foo = ???
    
    lazy val r1 = expensiveOperation1()
    lazy val r2 = expensiveOperation2()
    lazy val r3 = expensiveOperation3()
    
    (r1, r2, r3) match {
      case ("Value1", _, _)          => "1"
      case ("Value2", _, _)          => "2"
      case (_, List(1), _)           => "3"
      case (_, Nil, _)               => "4"
      case ("Value3", 1 :: tail, _)  => "5" + tail
      case (_, _, Foo("x", Some(x))) => x
      case (_, _, _)                 => "7"
    }
    

    如您所见,无需一直调用expensiveOperation2和expensiveOperation3,但尽管我将每个结果保存在lazy VAL上,但在创建Tuple3时,每个方法都会被调用。

    你知道吗?

    提前谢谢。

    1 回复  |  直到 6 年前
        1
  •  4
  •   Aleksey Isachenkov    6 年前

    尝试使用 scalaz.Need . https://static.javadoc.io/org.scalaz/scalaz_2.12/7.2.26/scalaz/Need.html

    case class Foo(bar: String, baz: Option[String])
    
    def expensiveOperation1(): String = {
        println("operation1")
        "Value3"
    }
    def expensiveOperation2(): List[Int] = {
        println("operation2")
        List(1, 2, 3)
    }
    def expensiveOperation3(): Foo = {
        println("operation3")
        Foo("x", Some("x"))
    }
    
    lazy val r1 = Need(expensiveOperation1())
    lazy val r2 = Need(expensiveOperation2())
    lazy val r3 = Need(expensiveOperation3())
    
    (r1, r2, r3) match {
        case (Need("Value1"), _, _)                => "1"
        case (Need("Value2"), _, _)                => "2"
        case (_, Need(List(1)), _)                 => "3"
        case (_, Need(Nil), _)                     => "4"
        case (Need("Value3"), Need(1 :: tail), _)  => "5" + tail
        case (_, _, Need(Foo("x", Some(x))))       => x
        case (_, _, _)                             => "7"
    }
    

        operation1
        operation2