Scala concepts: foldLeft and foldRight

A 'fold' allows you to perform the equivalent of a for-loop, but with a lot less code.

def foldMutable[I, O](
    initialState: O
)(items: List[I])(f: (O, I) => O): O = {
  var result: O = initialState
  items.foreach { item => result = f(result, item) }
  result
}

Becomes:

def foldMutable[I, O](initialState: O)(items: List[I])(f: (O, I) => O): O =
  items.foldLeft(initialState)(f)

So you can see how ta Scala solution that is immutable can be represented in a mutable form. Reverse is also possible.

The big difference is that to the user it is immutable, because you only specify the next value by adding an item to an accumulator.

This presents many possibilities, most important of which is to be able to develop code in a highly predictable and obvious manner, whereas in standard for-loops, many complications can arise (wrong indices, unexpected mutations).

def getUniqueCharacters(string: String): Set[Char] = {
  var setOfCharacters = Set.empty[Char]
  string.foreach { character =>
    setOfCharacters = setOfCharacters + character
  }
  setOfCharacters
}

assert(getUniqueCharacters("ABCDEABC") == Set('A', 'B', 'C', 'D', 'E'))

And in an immutable fashion:

def getUniqueCharacters(string: String): Set[Char] = {
  string.foldLeft(Set.empty[Char])(_ + _)
}

assert(getUniqueCharacters("ABCDEABC") == Set('A', 'B', 'C', 'D', 'E'))

The rule of thumb is: if you want a single result, use `foldLeft`, if you want a set of intermediate results, use scanLeft and scanRight.