I was working through the answers to Example of the difference between List.fold and List.foldBack trying to get my head around the difference between fold
and foldBack
. I understand the difference in application order now, but there's a difference in side-effects that I don't understand.
I used List.fold
and List.foldBack
for my testing. My accumulator functions that were basically equivalent to ::
, so that accumulation order would matter. The accumulator functions I used were as follows:
let f acc x =
// printfn "Folding %A into %A" x acc // Side-effect!
x :: acc
let f2 x acc =
// printfn "Folding %A into %A" x acc // Side-effect!
x :: acc
I understand from the F# reference that:
List.fold f [] [1; 2; 3; 4; 5] = (f (f (f (f (f [] 1) 2) 3) 4) 5)
and:
List.foldBack f2 [] [1; 2; 3; 4; 5] = (f2 1 (f2 2 (f2 3 (f2 4 (f2 5 [])))))
should both return true
, and they do. Great, I thought; I understand how it works. But just to make sure, I uncommented the side-effect lines from f
and f2
and ran List.fold f
and List.foldBack f2
again. Result of List.fold f [] [1; 2; 3; 4; 5]
with the printfn
line uncommented:
Folding 1 into []
Folding 2 into [1]
Folding 3 into [2; 1]
Folding 4 into [3; 2; 1]
Folding 5 into [4; 3; 2; 1]
val it : bool = true
Result of List.foldBack f2 [] [1; 2; 3; 4; 5]
with the printfn
line uncommented:
val it : bool = true
I was expecting "Folding N into [list]" to show up in both cases. But List.fold
executed the side effects of its accumulator function, and List.foldBack
did not.
Why is there a difference in side-effect execution between the two forms of fold
?