【发布时间】:2018-04-25 22:33:48
【问题描述】:
这个问题是 Scala 的模式匹配语法特有的。所以假设我有一些与此等价的代码:
def process(seq: Seq[SomeObjectType]): SomeReturnType = seq match {
case Seq() => // Return something
case s if s exists (o => o.somePropertyTest) => {
// Ok, the test is satisfied, now let's find
// that object in the sequence that satisfies
// it and do something with it
}
case _ => // Return something if no other case matches
}
现在很明显,这段代码的效率并不高,因为我检查了序列中是否有满足某些测试的元素,然后在这种情况下,我继续找到该元素并使用它,这可以有点像这样来避免遍历序列两次:
def process(seq: Seq[SomeObjectType]): SomeReturnType = seq match {
case Seq() => // Return something
case s => {
val obj = s find (o => o.somePropertyTest)
if !obj.isEmpty {
// Ok, the test is satisfied, and we have
// the object that satisfies it, obj, so
// do something with it directly
} else {
// Handle the no-match case here instead
}
}
}
但这违背了模式匹配的全部目的,尤其是在我进行测试之后有多种情况时。如果测试不通过,我仍然希望执行落到下一个案例,即如果没有元素满足条件,但我也想“保留”在测试中找到的序列的元素并直接使用它案例主体,类似于使用@ 为复杂案例命名并在其主体中使用该名称的方式。我正在尝试通过模式匹配做的事情吗?还是模式匹配太复杂而无法处理?
请注意,为了清楚起见,这是一个简化的示例。在我的实际问题中,序列很长,并且对序列的每个元素的测试包括构建一个相对较大的树并检查该树是否具有某些属性,因此仅处理低效的第一个版本确实不是一个选择.
【问题讨论】:
-
我一直希望 Scala 具有将任意表达式视为提取器的语法。想象一下,如果你能写
seq match { case { _.find(_.prop) }(o) => ... }。它具有完美的语义意义,并且很明显如何对其进行脱糖;只是没有语法。当函数式语言以不同于它们所代表的表达式的方式处理变量时,IMO 是一个明显的句法差距。 -
我同意!这将显着提高 Scala 模式匹配的功能和灵活性,这是该语言的核心特性之一。