Poucas coisas para mencionar aqui, antes de dar a resposta real:
- Sua pergunta não tem nada a ver
left
, é sobre a diferença entre reduzir e dobrar
- A diferença não é a implementação, basta olhar para as assinaturas.
- A questão não tem nada a ver com Scala em particular, é sobre os dois conceitos de programação funcional.
Voltar à sua pergunta:
Aqui está a assinatura de foldLeft
(também poderia ter sido foldRight
para o ponto que eu vou fazer):
def foldLeft [B] (z: B)(f: (B, A) => B): B
E aqui está a assinatura de reduceLeft
(novamente a direção não importa aqui)
def reduceLeft [B >: A] (f: (B, A) => B): B
Estes dois parecem muito semelhantes e, portanto, causaram confusão. reduceLeft
é um caso especial de foldLeft
(que, a propósito, significa que você às vezes pode expressar a mesma coisa usando qualquer um deles).
Quando você chama reduceLeft
say em a List[Int]
, literalmente reduz a lista inteira de números inteiros em um único valor, que será do tipo Int
(ou um supertipo de Int
, portanto [B >: A]
).
Quando você chama o foldLeft
say em um, List[Int]
ele dobrará a lista inteira (imagine rolar um pedaço de papel) em um único valor, mas esse valor nem precisa estar relacionado aInt
(daí [B]
).
Aqui está um exemplo:
def listWithSum(numbers: List[Int]) = numbers.foldLeft((List.empty[Int], 0)) {
(resultingTuple, currentInteger) =>
(currentInteger :: resultingTuple._1, currentInteger + resultingTuple._2)
}
Este método pega um List[Int]
e retorna um Tuple2[List[Int], Int]
ou (List[Int], Int)
. Ele calcula a soma e retorna uma tupla com uma lista de números inteiros e sua soma. A propósito, a lista é retornada para trás, porque usamos em foldLeft
vez defoldRight
.
Assista ao One Fold para dominá-los para uma explicação mais aprofundada.