2015-07-06 3 views
1

У меня есть образец кода Scala, и я хочу знать, почему я получаю ошибку в foldLeft, но не с foldRight?Scala: Value :: не является членом Int

val xs = List(1,2,3) 
val ys = List(4,5,6) 
(xs foldLeft ys) (_::_) // Error: Value :: is not a member of Int 
(xs foldRight ys) (_::_) // Res: List(1, 2, 3, 4, 5, 6) 

Я новичок в Scala, поэтому, пожалуйста, ответьте как можно проще. Спасибо

ответ

3

Аргументы для оператора (функции), переданные в foldLeft, и foldRight находятся в обратном порядке.

Итак, в foldLeft ваш _ :: _ начинается с ys :: xs.head, что не имеет никакого смысла.

С foldRight самая внутренняя операция - xs.last :: ys, что хорошо.

Порядок аргумент имеет больше смысла в версиях оператора: z /: ws толкает z righward через ws (т.е. foldLeft), в то время как ws :\ z толкает z влево (т.е. foldRight). И порядок аргументов внутри согласуется с порядком z против w выше.

2

foldLeft и foldRight имеют разные подписи, они принимают разные аргументы

def foldLeft[B](z: B)(op: (B, A) => B): B 
def foldRight[B](z: B)(op: (A, B) => B): B 

Посмотрите на тип функции op в обоих из них. Для foldLeft левый аргумент - это тип коллекции, которую вы складываете (в вашем случае int), тогда как для foldRight это тип результата (в вашем случае коллекция).

Так что вы хотите использовать другую функцию в foldLeft, если вы хотите, чтобы каждый последующий элемент добавлялся к вашему результирующему списку.

1

Короче говоря, операция «::» недоступна в Int, только для коллекций. Если вы выполняете '(хз foldLeft YS) _ в Scala РЕПЛ, вы видите, что это приводит к функции

((List[Int], Int) => List[Int]) => List[Int] = <function1> 

Таким образом, первый операнд является List [Int] и второй Int. Обратите внимание, что любой оператор, заканчивающийся на ':', является особым, так как он работает на правой стороне, используя левый аргумент. Это называется «право-ассоциативным», тогда как по умолчанию обычно «лево-ассоциативный».

Поэтому 'aList :: anInt' преобразуется в 'anInt.::(aList)', и это вызывает проблему, поскольку Int не имеет метода «::».

В случае с «foldLeft» вам нужна лево-ассоциативная функция, чтобы добавить один элемент, например «: +». Так что это то работает:

(xs foldLeft ys)(_ :+ _) 

Обратите внимание, что результат довольно сильно отличается от foldRight поэтому не забудьте подобрать к правильному для вашей ситуации.

Смежные вопросы