Search code examples
scalaunit-testingfunctional-programmingscalatest

Pass function to another function in Scala, get "Missing parameter type for expanded function Scala"


I wrote the following test:

  "List" should "be [3, 4] for condition '_ <= 2'" in {
    val l: List[Int] = List(1, 2, 3, 4)
    assertResult(List(3, 4))(dropWhile(l, _ <= 2))
  }

For function:

  def dropWhile[A](l: List[A], f: A => Boolean): List[A] = l match {
    case Nil => List()
    case Cons(h, t) => if (f(h)) dropWhile(t, f) else t
  }

However, I get missing parameter type for expanded function when pass _ <= 2 to dropWhile(l, _ <= 2). What's the problem? How can I fix it?


Solution

  • The problem is the way type inference works in Scala 2. At that point the compiler doesn't know yet that A is Int thus it doesn't know how to expand _ <= 2

    There are multiple ways to solve this problem.

    1. Use Scala 3 which improved in this reward, and it should just work.

    2. Manually specify the type parameter:

    dropWhile[Int](l, _ <= 2)
    // Or
    dropWhile(l, (x: Int) => x <= 2)
    
    1. (my favourite one) move the function to its own parameter list so that type inference works as expected in Scala 2; also it provides a better API IMHO.
    // Definition site
    def dropWhile[A](l: List[A])(f: A => Boolean): List[A] = ???
    // Call site
    dropWhile(l)(_ <= 2) // Or dropWhile(l)(x => x <= 2)