1

我有这样的构造:

if(condition1)
  lengthyOperation1
else if(condition2)
  lengthyOperation2
else if(condition3)
  lengthyOperation3
...
else
  lastLengthyOperation

我想用以下方式表达:

lazy val seq = Seq(
  condition1 -> lengthyOperation1,
  condition2 -> lengthyOperation2,
  condition3 -> lengthyOperation3,
  ...
  true -> lastLengthyOperation
)

seq.find(_._1).match { case(_, v) => v }

问题是最后一行的评估在到达“seq”时会执行所有冗长的操作。我该如何做到这一点,以便仅在需要时才执行冗长的操作?

注意:条件不是同一表达式的可能模式匹配(即我不能为此使用单个匹配语句)

编辑:我应该为此使用 Stream 吗?

4

2 回答 2

0

我猜你的意思是Seq,不是Map

您可以在这里使用Seq而不是if序列,尽管我认为它不可读。

你应该使用getOrElseafter find。假设每个lengthyOperationN都是一个函数:

seq.find(_._1).map{_._2}.getOrElse(lastLengthyOperation).apply()
于 2013-08-14T13:27:14.223 回答
0

你的方法的问题是你在错误的地方懒惰。当你声明

lazy val seq = Seq(
  condition1 -> lengthyOperation1,
  ...
)

然后,一旦您 touch seq,无论您触摸哪一个,都会使用其所有冗长的操作对整个序列进行评估。序列的元素是严格的。

你可以用 s 做你想做的事Stream,但我想用 s 做起来更容易,Options 就是为此目的而设计的。让我们在选项上声明一个辅助隐式函数。如果它被调用Some,它不会做任何事情。如果它被调用None,它会检查一个条件,如果满足,则返回Some(result)

implicit class IfOption[A](opt: Option[A]) {
  def ?>[B >: A](condition: Boolean, result: => B): Option[B] =
    opt.orElse(if (condition) Some(result) else None);
}

现在我们可以做类似的事情

println(
    None
      ?> (1 != 1, "A")
      ?> (2 == 2, "B")
      ?> (3 == 2, "C")
)

其中打印表达式的类型是Option[String]and prints Some(B),或者

println(
    None
      ?> (1 != 1, "Yes")
      ?> (2 != 2, "No")
      ?> (3 != 2, "heck")
      getOrElse ("ah")
)

其中类型只是“字符串”。

于 2013-08-14T14:05:36.103 回答