Скала: как избежать мутации? - PullRequest
2 голосов
/ 29 января 2012

Это обычное дело, когда нужно накопить некоторые данные.Я привык к этому, добавляя куски данных в массив.Но в scala это плохая практика, так как я могу избежать этого?

Ответы [ 3 ]

4 голосов
/ 30 января 2012

Ну, есть два общих способа борьбы с накоплением: рекурсия и складывание.Давайте рассмотрим очень простые примеры каждого из них, чтобы вычислить сумму значений списка.

def sumRecursively(list: List[Int]): Int = {
  def recurse(list: List[Int], acc: Int): Int =
    if (list.isEmpty) acc
    else recurse(list.tail, acc + list.head)
  recurse(list, 0)
}

def sumFolding(list: List[Int]): Int =
  list.foldLeft(0){ case (acc, n) => acc + n }

Существует множество вариаций, которые лучше обрабатывают тот или иной случай.

2 голосов
/ 29 января 2012

В большинстве случаев операции «map» и «flatMap» используются для функциональной генерации структур данных. Оба начинают с одной структуры данных, применяют некоторые операции к каждому элементу в ней и возвращают новую структуру данных той же формы, что и оригинал. Они отличаются только тем, как заполняется новая структура данных. Эти два настолько распространены и настолько мощны, что в Scala есть специальный синтаксис - для понимания - для их поддержки. Внешнее понимание выглядит внешне похожим на цикл for в стиле Java, но фактически компилируется в серию вызовов map и flatMap (среди нескольких других).

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

Стоит также отметить, что «map» и «flatMap» на самом деле являются частными случаями другой, более мощной функции: «fold». "fold" (реализованный как "foldLeft" и "foldRight" по техническим причинам) может использоваться как для построения структур данных, так и для их разбивки.

2 голосов
/ 29 января 2012

На самом деле это не так. Вы можете использовать Vector в Scala, который является частью пакета scala.collection.immutable по умолчанию. Это создаст неизменную коллекцию, которая будет возвращать новый (другой) экземпляр каждый раз, когда вы добавляете его.

Дополнительная информация:

http://www.scala -lang.org / доку / файлы / сборники-апи / collections_15.html

...