Разница между сгибом и сгибом слева или сгибом справа? - PullRequest
61 голосов
/ 06 июня 2011

ПРИМЕЧАНИЕ. Я пользуюсь Scala 2.8 - может ли это быть проблемой?

Почему я не могу использовать функцию fold так же, как foldLeft или foldRight?

В Set scaladoc написано, что:

Результатом свертывания может быть только супертип параметра типа этой параллельной коллекции T.

Но я не вижу параметра типа T в сигнатуре функции:

def fold [A1 >: A] (z: A1)(op: (A1, A1) ⇒ A1): A1

В чем разница между foldLeft-Right и fold, и как я могу использовать последние?

РЕДАКТИРОВАТЬ: Например, как мне написать сгиб, чтобы добавить все элементы в список? С foldLeft это будет:

val foo = List(1, 2, 3)
foo.foldLeft(0)(_ + _)

// now try fold:
foo.fold(0)(_ + _)
>:7: error: value fold is not a member of List[Int]
  foo.fold(0)(_ + _)
    ^

Ответы [ 5 ]

66 голосов
/ 06 июня 2011

Краткий ответ:

foldRight ассоциируется справа.Т.е. элементы будут накапливаться в порядке справа налево:

List(a,b,c).foldRight(z)(f) = f(a, f(b, f(c, z)))

foldLeft ассоциируется слева.Т.е. аккумулятор будет инициализирован и элементы будут добавлены в аккумулятор в порядке слева направо:

List(a,b,c).foldLeft(z)(f) = f(f(f(z, a), b), c)

fold является ассоциативным в том порядке, в котором элементыскладываются вместе не определяется.Т.е. аргументы fold образуют моноид .

53 голосов
/ 06 июня 2011

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

8 голосов
/ 09 июня 2011

Вы правы в том, что старая версия Scala была проблемой.Если вы посмотрите на страницу scaladoc для Scala 2.8.1, вы не увидите там определенную складку (что соответствует вашему сообщению об ошибке).Очевидно, fold была введена в Scala 2.9.

3 голосов
/ 20 апреля 2017

Согласен с другими ответами.Мысль о простом иллюстративном примере:

 object MyClass {
 def main(args: Array[String]) {
val numbers = List(5, 4, 8, 6, 2)
 val a =  numbers.fold(0) { (z, i) =>
 {
     println("fold val1 " + z +" val2 " + i)
  z + i

 }
}
println(a)
 val b =  numbers.foldLeft(0) { (z, i) =>
 println("foldleft val1 " + z +" val2 " + i)
  z + i

}
println(b)
   val c =  numbers.foldRight(0) { (z, i) =>
   println("fold right val1 " + z +" val2 " + i)
  z + i

}
println(c)
 }
}

Результат не требует пояснений:

fold val1 0 val2 5
fold val1 5 val2 4
fold val1 9 val2 8
fold val1 17 val2 6
fold val1 23 val2 2
25
foldleft val1 0 val2 5
foldleft val1 5 val2 4
foldleft val1 9 val2 8
foldleft val1 17 val2 6
foldleft val1 23 val2 2
25
fold right val1 2 val2 0
fold right val1 6 val2 2
fold right val1 8 val2 8
fold right val1 4 val2 16
fold right val1 5 val2 20
25
3 голосов
/ 06 июня 2011

Для вашего конкретного примера вы бы закодировали его так же, как и с foldLeft.

val ns = List(1, 2, 3, 4)
val s0 = ns.foldLeft (0) (_+_) //10
val s1 = ns.fold (0) (_+_) //10
assert(s0 == s1)
...