4
votes

I'm posting this question out of curiosity to see if someone knows how pattern matching works in the following case. Let's say I have a function value defined as follows:

val f = (s: String) => s.toInt

It's type is of course String => Int. Now I want to create a new function based on pattern matching the output of whatever is passed to this function. I can define that as follows:

val f2 = f(_: String) match {
  case i: Int => i + 2
}

Now my new function is also from String => Int, but it adds 2 during the process. It can be called as follows:

scala> f2("3")
res0: Int = 5

If I do the same without doing partial application then I get a match based on the function itself:

val f3 = f match {
  case x => "matched: " + x
}

Now the value f3 is assigned "matched <function1>" because it called match with 'f' as the value.

So my question is this, how does Scala tell these two apart? They are both function values and both are of type String => Int. In fact, if I assign the partially applied function value to a temporary variable tmp before running match, then it behaves the same as f3:

val tmp = f(_: String)
val f4 = tmp match {
  case x => "matched: " + x
}

Now f4 is assigned "matched <function1>" instead of being a function String => Int.

I can see the value in wanting to do either, I'm just curious how it is done. Is this just some magic Scala added that somehow it figures out you are partially applying a function in the context of a match so it will generate something different...

1

1 Answers

9
votes

That's just how underscores work.

f(_: String) match {
  case i: Int => i + 2
}

is a shorthand for

(x: String) => (f(x) match {
  case i: Int => i + 2
})

(parentheses added to make things more clear) but your other examples are equivalent to

(x: String => f(x)) match {
  case y => "matched: " + y
}