This problem is kind of specific to Scala's pattern matching syntax. So let's say I have some code equivalent to this:
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
}
Now obviously, this code is not as efficient as it could be since I check if there is an element in the sequence that satisfies some test, then in that case I go ahead and find the element and work with it, which can be done somewhat like this to avoid traversing the sequence twice:
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
}
}
}
But this defeats the whole purpose of pattern matching, especially when there are multiple cases after the one where I do the test. I still want the execution to fall to the next case if the test does not pass, i.e. if no element satisfies the condition, but I also want to "retain" the element of the sequence that was found in the test and use it directly in the case body, kind of similar to the way one can use @ to give a name to a complex case and use that name in its body. Is what I'm trying to do possible with pattern matching? Or is it just too complicated for pattern matching to be able to handle it?
Note that this is a simplified example for clarity. In my actual problem, the sequences are long and the test on each element of a sequence consists in building a relatively big tree and checking whether some properties hold for that tree, so it is really not an option to just do with the inefficient first version.
seq match { case { _.find(_.prop) }(o) => ... }. It makes perfect semantic sense and it's obvious how to desugar it; there's just no syntax for it. IMO it is an obvious syntactic gap when a functional language treats variables differently than the expressions they stand for. - Owen