Scala: накапливать var из коллекции функциональным способом (то есть без vars)

Это вопрос новичков

У меня есть следующий код:

var total = 0L
docs.foreach(total += _.length)

в документах У меня есть коллекция объектов с свойством .length

Мне хотелось бы что-то вроде:

val total = docs.[someScalaMethod](0, (element, acum) => acum + element.length )

Я имею в виду метод, который выполняет итерацию каждого элемента, передающего переменную аккумулятора...

Первый нулевой проход я должен быть начальным значением аккумулятора var.

Как это можно достичь?

Ответы

Ответ 1

Это называется сгибом. Это почти то, что вы заявили:

docs.foldLeft(0)((accum, element) => accum + element.length)

для версии, которая перемещает коллекцию слева направо (обычно предпочтительнее, справа налево - foldRight, а 2.9 имеет fold, который может начинаться где угодно, но имеет ограничения на то, как он может преобразовать тип).

Как только вы привыкнете к этому, есть кратковременная версия складки влево, где аккумулятор идет слева (думайте, что он проталкивается слева направо через список), и вы используете заполнители для переменной имена, поскольку вы используете их только один раз: (0 /: docs)(_ + _.length)

Ответ 2

docs map { _.length } reduce { _ + _ }

или (спасибо переходит к Луиджи Плинге)

docs.map(_.length).sum

Ответ 3

Вот версия Scalaz:

docs.foldMap(_.length)

Это эквивалентно docs.map(_.length).sum, но занимает всего один проход. Кроме того, работает со всеми monoids.