Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does providing a partial function to map throw at runtime rather than give a compile error?

Apologies if this is obvious but I am new to scala and I am getting two unexpected behaviors with the following code:

Seq(1, "a", 2, "b") map { 
    case i: Int => i+1
}

1) I would have expected to get back a collection where the strings are unchanged and the numbers are incremented by 1 but instead I get an error.

2) I believe the case i: Int => i + 1 syntax represents a partial function which is defined for Ints. But it seems map takes a total function, so why does this even compile? Wouldn't it be better for the compiler to help me out? It is always better to move runtime exceptions to compile time exceptions.

like image 450
Stan L Avatar asked Oct 15 '25 05:10

Stan L


1 Answers

map() does not take a partial function as the passed parameter, but collect() does.

Seq(1, "a", 2, "b") collect {
  case i: Int => i+1
}
//res0: Seq[Int] = List(2, 3)

Notice how input that is not defined for the partial function is not passed through but is simply dropped. What you don't want dropped needs a handler, even if it's just a case _ => default handler.

Seq(1, "a", 2, "b", 'z') collect {
  case i: Int    => i+1        //increment ints
  case c: Char   => c.toUpper  //capitalize chars
  case s: String => s          //strings pass through
}
//res0: Seq[Any] = List(2, a, 3, b, Z)

When you pass a partial function to map() the compiler does not complain because trait PartialFunction[-A, +B] extends (A) => B. In other words, a partial function is a type of function.

It's also worth noting that, when dealing with partial functions...

It is the responsibility of the caller to call isDefinedAt before calling apply...

So we can conclude that collect() does that and map() doesn't.

like image 107
jwvh Avatar answered Oct 17 '25 19:10

jwvh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!