injoy
injoy

Reputation: 4383

Expression of type B => List[B] doesn’t conform to expected type List[Int] when reverse a list in Scala

Working on a function to reverse a list in Scala using the foldLeft function:

def reverseWithFold(ls: List[Int]): List[Int] =
        ls.foldLeft(List[Int]())((c, _) => _:::c)

it got compiling errors: Expression of type List[B_] => List[Int] doesn’t comforrm to expected type List[Int] (PS: I know my solution is not correct)

Can I know what does it mean? In _:::c here, the _ represents the c in (c, _), and c is a List[Int] type, so in my opinion, _:::c should be the concatenation of two List[Int]. It should conform with the expected type, right?

Upvotes: 0

Views: 401

Answers (3)

jwvh
jwvh

Reputation: 51271

  • ls - a list of type List[Int]
  • foldLeft - Create something new from the Int elements of ls.
  • List[Int]() - That something new will be another List[Int]. Start with an empty one.
  • (c, _) - With each step receive the List being built, we'll call it c, and an Int from ls, but don't give it a name (i.e. throw it away).
  • _:::c - Try to concatenate 2 lists together. One is the c list that we're building and the other is...nothing. It's not a List or an Int. It's an unnamed parameter, but we don't have any of those. Of the 2 received parameters, one was named c and the other was discarded.

Here's one way to fix it: (c, n) => List(n):::c (concatenate 2 lists together)

Here's a better way to fix it: (c, n) => n::c (prepend a new element to the head of this list)

Using unnamed parameters: ls.foldLeft(List[Int]())(_.::(_))

Upvotes: 3

Yevhenii Popadiuk
Yevhenii Popadiuk

Reputation: 1054

You see, you can write both List(1,2,3).reduce((x, y) => x + y) or List(1,2,3).reduce(_ + _). Here, (x, y) => x + y and _ + _ are functions, first more obvious and second one is function, where each underscore is replaced by one of parameters.

What you doing here is (c, _) => _:::c is trying to combine both. But, really, you just telling scala compiler:

  1. I have function of two agruments: c and another one is discarded.
  2. This function returns function without specified type. (Example: (Int, Int) => (Int => Int) = (a: Int, _) => _ * 2)

What you can do here is

rewrite using only underscores:

ls.foldLeft(List.empty[Int])(_.::(_))

or rewrite without discarding:

ls.foldLeft(List.empty[Int])((acc, cur) => cur :: acc)

Upvotes: 3

Andrey Tyukin
Andrey Tyukin

Reputation: 44992

Underscores are not valid variable names, they are used to ignore variables. The two underscores in (c, _) and _ ::: c are unrelated.

  • (c, _) => { ... } ignores the second parameter completely, it's gone.
  • _ ::: c is a shortcut for the lambda expression x => x ::: c, which expects an x that is a List[B_] for some unknown type B_ that cannot be inferred, because it's not expected, and it's nowhere to be found in your code.

If you wanted to prepend the second argument to the first, you would have to write something like

ls.foldLeft(List.empty[Int])((c, x) => x :: c)

or even

ls.foldLeft(List.empty[Int])(_.::(_))

Upvotes: 3

Related Questions