避免在模式匹配案例

时间:2018-04-25 22:33:49

标签: scala pattern-matching

此问题特定于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
        }
    }
}

但是这会破坏模式匹配的整个目的,特别是在我进行测试的情况之后有多个案例时。如果测试没有通过,我仍然希望执行落到下一种情况,即如果没有元素满足条件,但我也想“保留”测试中找到的序列的元素并直接使用它案例主体,类似于可以使用@为复杂案例命名并在其正文中使用该名称的方式。我正在尝试用模式匹配做什么?或者它是否太复杂,模式匹配能够处理它?<​​/ p>

请注意,为简洁起见,这是一个简化示例。在我的实际问题中,序列很长,对序列的每个元素的测试包括构建一个相对较大的树并检查某个属性是否适用于该树,因此实际上不能选择低效的第一个版本

2 个答案:

答案 0 :(得分:2)

您可以使用seriation, dedextend, fpc, flexmix方法定义自定义extractor object。限制是你不能在模式匹配中内联创建这样的对象。您必须在匹配之前显式创建它。例如:

unapply

答案 1 :(得分:0)

未经过测试,但是这样:

def process(seq: Seq[SomeObjectType]): SomeReturnType = seq match {
    case Seq() => // Return something
    case x +: xs if x.somePropertyTest == desiredProperty => something(x)
    case x +: xs => process(xs)
}

这是有效的,因为Seq是一个递归结构,由进程递归。