Pattern matching vs if-else
I'm novice in Scala. Recently I was writing a hobby app and caught myself trying to use pattern matching instead of if-else in many cases.
user.password == enteredPassword match {
case true => println("User is authenticated")
case false => println("Entered password is invalid")
}
instead of
if(user.password == enteredPassword)
println("User is authenticated")
else
println("Entered password is invalid")
Are these approaches equal? Is one of them more preferrable than another for some reason?
class MatchVsIf {
def i(b: Boolean) = if (b) 5 else 4
def m(b: Boolean) = b match { case true => 5; case false => 4 }
}
I'm not sure why you'd want to use the longer and clunkier second version.
scala> :javap -cp MatchVsIf
Compiled from "<console>"
public class MatchVsIf extends java.lang.Object implements scala.ScalaObject{
public int i(boolean);
Code:
0: iload_1
1: ifeq 8
4: iconst_5
5: goto 9
8: iconst_4
9: ireturn
public int m(boolean);
Code:
0: iload_1
1: istore_2
2: iload_2
3: iconst_1
4: if_icmpne 11
7: iconst_5
8: goto 17
11: iload_2
12: iconst_0
13: if_icmpne 18
16: iconst_4
17: ireturn
18: new #14; //class scala/MatchError
21: dup
22: iload_2
23: invokestatic #20; //Method scala/runtime/BoxesRunTime.boxToBoolean:(Z)Ljava/lang/Boolean;
26: invokespecial #24; //Method scala/MatchError."<init>":(Ljava/lang/Object;)V
29: athrow
And that's a lot more bytecode for the match also. It's fairly efficient even so (there's no boxing unless the match throws an error, which can't happen here), but for compactness and performance one should favor if
/else
. If the clarity of your code is greatly improved by using match, however, go ahead (except in those rare cases where you know performance is critical, and then you might want to compare the difference).
Don't pattern match on a single boolean; use an if-else.
Incidentally, the code is better written without duplicating println
.
println(
if(user.password == enteredPassword)
"User is authenticated"
else
"Entered password is invalid"
)
One arguably better way would be to pattern match on the string directly, not on the result of the comparison, as it avoids "boolean blindness". http://existentialtype.wordpress.com/2011/03/15/boolean-blindness/
One downside is the need to use backquotes to protect the enteredPassword variable from being shadowed.
Basically, you should tend to avoid dealing with booleans as much as possible, as they don't convey any information at the type level.
user.password match {
case `enteredPassword` => Right(user)
case _ => Left("passwords don't match")
}