Выражение типа 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:

  1. У меня есть функция двух агрументов: c и еще один отбрасывается.
  2. Эта функция возвращает функцию без указанного типа. (Пример: (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]())(_.::(_))

Другие вопросы по тегам