【问题标题】:How can I do pattern matching on tuple with lazy initialization?如何使用延迟初始化对元组进行模式匹配?
【发布时间】:2018-09-05 16:08:57
【问题描述】:

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

这是一个简化的例子。

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"
}

如你所见,没有必要一直调用昂贵操作2和昂贵操作3,但是虽然我将每个结果保存在惰性值上,但在我创建Tuple3的那一刻,每个方法都会被调用。

我可以创建一个容器 LazyTuple3,其中包含三个按名称调用的参数来解决这个问题,但我会遇到一个新问题,unapply 方法 (LazyTuple3.unapply) 返回一个选项,所以在第一个“案例”之后每个方法将被调用。

我可以用嵌套的“if”或“match”来解决这个问题,但我想给一个“match”的机会,我发现它更清楚。

有什么想法吗?

提前致谢。

【问题讨论】:

    标签: scala pattern-matching lazy-initialization


    【解决方案1】:

    尝试使用scalaz.Needhttps://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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-19
      • 1970-01-01
      • 2011-08-16
      • 2015-05-21
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多