Разница между кратным и метод использовать-foldleft и foldRight?
примечание: Я нахожусь на Scala 2.8-может ли это быть проблемой?
почему я не могу использовать fold
функция так же, как foldLeft
или foldRight
?
на установить scaladoc он говорит, что:
результатом сворачивания может быть только супертип параметра типа этой параллельной коллекции
T
.
но я не вижу параметра типа T
в сигнатуре функции:
def fold [A1 >: A] (z: A1)(op: (A1, A1) ⇒ A1): A1
что такое разница между foldLeft-Right
и fold
, и как я могу использовать последний?
EDIT: например, как бы я написал складку, чтобы добавить все элементы в список? С 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 ответов:
вы правы о том, что старая версия Scala является проблемой. Если вы посмотрите на страница scaladoc для Scala 2.8.1 вы не увидите там сгиба (что согласуется с вашим сообщением об ошибке). Видимо,
fold
был представлен в Scala 2.9.
короткий ответ:
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
сформировать моноидом.
fold
вопрекиfoldRight
иfoldLeft
, не дает никаких гарантий относительно порядка, в котором будут обрабатываться элементы коллекции. Вы, вероятно, захотите использоватьfold
, с его более ограниченной сигнатурой, с параллельными коллекциями, где отсутствие гарантированного порядка обработки помогает параллельной коллекции реализовать сворачивание параллельным способом. Причина изменения подписи аналогична: с дополнительными ограничениями легче сделать параллель складывать.
для вашего конкретного примера вы бы закодировали его так же, как и с foldLeft.
val ns = List(1, 2, 3, 4) val s0 = ns.foldLeft (0) (_+_) //10 val s1 = ns.fold (0) (_+_) //10 assert(s0 == s1)
согласен с другими ответами. подумайте о том, чтобы дать простой иллюстративный пример:
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