From your point of view, there is no difference. They are both values defined by using “function literals”. The REPL shows you that they are both “Lambda…” which stands for function literal:
➜ scala
Welcome to Scala 3.1.0 (11.0.13, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
scala> val status: Int => String = { case 200 => "ok"; case 500 => "error"; case other => "unknown" }
val status: Int => String = Lambda$1362/0x00000008406bc840@299a43d9
scala> val status2: Int => String = x => if x == 200 then "ok" else if x == 500 then "error" else "unknown"
val status2: Int => String = Lambda$1384/0x00000008406f1840@1be3f8f8
You are simply using pattern matching (plus the partial function syntax) in the first one (then making it a complete function by having a final case that matches every pattern), and if/else
in the second one. The only difference is a matter of choice/taste between pattern matching versus if/else
. It’s not related to anonymous functions. You could write these same functions with def
too:
scala> def stat(x: Int): String = x match
| case 200 => "ok"
| case 500 => "error"
| case other => "unknown"
|
def stat(x: Int): String
scala> def stat2(x: Int): String =
| if x == 200 then "ok"
| else if x == 500 then "error"
| else "unknown"
|
def stat2(x: Int): String
So far, no difference. Just if/else versus pattern matching. Doesn’t matter if it’s an anonymous function or not.
Some info on Partial Functions
I think your confusion might be coming from the Partial Function Syntax (which lets you skip x match
):
{ case 200 => "ok"; ... }
Technically, if you didn’t have the LAST case case other => ...
that matches every other input, then there would be a difference. Unlike if/else
this syntax allows you to leave the “final else part” undefined. Let’s try it:
scala> val status: Int => String = { case 200 => "ok"; case 500 => "error" }
val status: Int => String = Lambda$1406/0x00000008406fd040@3dded90a
scala> status(123)
scala.MatchError: 123 (of class java.lang.Integer)
at repl$.rs$line$5$.$init$$$anonfun$1(rs$line$5:1)
at repl$.rs$line$5$.$init$$$anonfun$adapted$1(rs$line$5:1)
... 30 elided
Let’s take a look at the book “Programming in Scala” 5th Edition by Odersky, Venner, Spoon, Sommers. On Page 292-293 (I modified a bit):
One other generalization is worth noting: a sequence of cases gives you a
partial function.
scala> val second: List[Int] => Int = { case x :: y :: _ => y }
-- Warning:
1 |val second: List[Int] => Int = { case x :: y :: _ => y }
| ^
| match may not be exhaustive.
|
| It would fail on pattern case: List(_), Nil
val second: List[Int] => Int = Lambda$1594/0x000000084079b840@7ac90dab
The typical example of a partial function is a pattern matching function lit-
eral like the one in the previous example. In fact, such an expression gets
translated by the Scala compiler to a partial function by translating the pat-
terns twice—once for the implementation of the real function, and once to
test whether the function is defined or not.
For instance, the function literal { case x :: y :: _ => y }
gets translated
to the following partial function value:
new PartialFunction[List[Int], Int]:
def apply(xs: List[Int]) =
xs match
case x :: y :: _ => y
def isDefinedAt(xs: List[Int]) =
xs match
case x :: y :: _ => true
case _ => false