Reputation: 4383
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
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
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:
c
and another one is discarded.(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
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