I noticed that there is no || operator available when pattern matching - is | short circuited?
Asked
Active
Viewed 610 times
4
-
Official SLS says that - The alternative pattern matches a value v if at least one its alternatives matches v, so i think that would be at least logical, to be short-circuted, cause this operator is not boolean or, but a denotes a pattern alternative – 4lex1v Oct 21 '13 at 20:34
-
See also: [Pattern matching with conjunctions (PatternA AND PatternB)](http://stackoverflow.com/questions/2261358/pattern-matching-with-conjunctions-patterna-and-patternb) – J Cracknell Oct 21 '13 at 20:38
2 Answers
10
In pattern matching, |
is short circuited. You can't call unapply
or the like (with returned parameters) with the or-operator, where side-effects might be more likely. So short-circuiting is purely an optimization technique (won't affect the correctness of the code except in extraordinary cases such as a side-effecting equals method). This does mean you are limited in your ability to short circuit or not for performance or side-effecting reasons.
To see this, if we write this code:
def matchor(s: String) = s match {
case "tickle" | "fickle" => "sickle"
case _ => "hammer"
}
We see this bytecode (in part)
public java.lang.String matchor(java.lang.String);
Code:
0: aload_1
1: astore_2
2: ldc #12; //String tickle
4: aload_2
5: astore_3
6: dup
7: ifnonnull 18
10: pop
11: aload_3
12: ifnull 25
15: goto 31
18: aload_3
19: invokevirtual #16; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
22: ifeq 31
25: iconst_1
26: istore 4
28: goto 66
31: ldc #18; //String fickle
33: aload_2
...
66: iload 4
68: ifeq 78
71: ldc #20; //String sickle
73: astore 6
75: goto 82
...
82: aload 6
84: areturn
See the jump on line 28 to avoid testing the "fickle"
case? That's the short-circuit.

Rex Kerr
- 166,841
- 26
- 322
- 407
-
-
-
-
It's really easy to get bytecode, by the way. This is not some kind of heroics! `javap -c -private MyClassName` on the command-line will do it. – Rex Kerr Oct 23 '13 at 20:58
3
|
short-circuits.
object First {
def unapply(str: String): Boolean = {
println("in First")
str == "first"
}
}
object Second {
def unapply(str: String) = {
println("in Second")
str == "second"
}
}
object Run extends App {
"first" match {
case First() | Second() => None
}
//Output: In First
"first" match {
case Second() | First() => None
}
//Output: In Second\nIn First
}

Stuart Harrell
- 127
- 6