Выражение типа B => List[B] не соответствует ожидаемому типу List[Int] при обращении списка в Scala
Работаем над функцией, которая переворачивает список в Scala с помощью функции foldLeft:
def reverseWithFold(ls: List[Int]): List[Int] =
ls.foldLeft(List[Int]())((c, _) => _:::c)
он получил ошибки компиляции: Expression of type List[B_] => List[Int] doesn’t comforrm to expected type List[Int]
(PS: я знаю, что мое решение не является правильным)
Могу ли я знать, что это значит? В _:::c
здесь _
представляет c
в (c, _)
, а также c
это List[Int]
типа, так по моему, _:::c
должно быть объединение двух List[Int]
, Это должно соответствовать ожидаемому типу, верно?
3 ответа
Подчеркивания не являются допустимыми именами переменных, они используются для игнорирования переменных. Два подчеркивания в (c, _)
а также _ ::: c
не связаны.
(c, _) => { ... }
полностью игнорирует второй параметр, он пропал_ ::: c
является сокращением для лямбда-выраженияx => x ::: c
, который ожидаетx
этоList[B_]
для какого-то неизвестного типаB_
это не может быть выведено, потому что это не ожидаемо, и его нигде нет в вашем коде.
Если вы хотите добавить второй аргумент к первому, вам нужно написать что-то вроде
ls.foldLeft(List.empty[Int])((c, x) => x :: c)
или даже
ls.foldLeft(List.empty[Int])(_.::(_))
Вы видите, вы можете написать как List(1,2,3).reduce((x, y) => x + y)
или же List(1,2,3).reduce(_ + _)
, Вот, (x, y) => x + y
а также _ + _
являются функциями, первый более очевидный, а второй является функцией, где каждое подчеркивание заменяется одним из параметров.
Что вы делаете здесь (c, _) => _:::c
пытается объединить оба. Но, на самом деле, вы просто говорите компилятору scala:
- У меня есть функция двух агрументов:
c
и еще один отбрасывается. - Эта функция возвращает функцию без указанного типа. (Пример:
(Int, Int) => (Int => Int) = (a: Int, _) => _ * 2
)
Что вы можете сделать здесь
переписать, используя только подчеркивание:
ls.foldLeft(List.empty[Int])(_.::(_))
или переписать, не выбрасывая:
ls.foldLeft(List.empty[Int])((acc, cur) => cur :: acc)
ls
- список типовList[Int]
foldLeft
- Создать что-то новое изInt
элементыls
,List[Int]()
- Это что-то новое будет другимList[Int]
, Начните с пустого.(c, _)
- с каждым шагом получайтеList
будучи построенным, мы назовем этоc
иInt
отls
, но не называйте его (то есть выбрасывайте)._:::c
- Попробуйте объединить 2 списка вместе. Один из нихc
список, который мы строим, а другой... ничего. Это неList
илиInt
, Это неназванный параметр, но у нас его нет. Из 2 полученных параметров один был названc
а другой был отброшен.
Вот один из способов исправить это: (c, n) => List(n):::c
(объединить 2 списка вместе)
Вот лучший способ это исправить: (c, n) => n::c
(добавьте новый элемент в начало этого списка)
Используя неназванные параметры: ls.foldLeft(List[Int]())(_.::(_))