Wed Jun 17 14:47:19 EDT 2009

```roconnor at theorem.ca wrote:
> On Tue, 16 Jun 2009, Neil Mitchell wrote:
>
>> What is the need for swap' ? Things like foldl' solve space leaks,
>> what does swap' solve? I fully agree on the addition of swap.
>
> I'm not sure what swap' solves.  I just think it has a pretty symmetry to
> it.  I presume one of these pro-strict-swap people can come up with an
> example of where swap' solves a problem.

Sure.

f (x, y) z = let !t = x+z in (t, y)

bar1 xs = foldl' ((swap' .) . f) (0, 0) xs
bar2 xs = foldl' ((swap  .) . f) (0, 0) xs

Prelude Swap> bar1 [0..1000000]
(250000000000,250000500000)
Prelude Swap> bar2 [0..1000000]
(*** Exception: stack overflow

Actually, "swap" works fairly well most of the time, because in addition
to its laziness, ghc's garbage collector does short-cut evaluation of
record selectors. So if the code just builds up a chain of swaps, GC
will compress that chain very nicely.

But I still prefer the strict version.

Bertram

P.S. I'd problably write your example as

foo x []       = (x, 0)
foo x [y]      = (0, x + y)
foo x (y:z:xs) = let !t = x + y + z in foo t xs

or, if I wanted to do something fancy,

foo x xs = r where
(c, d, r) = go x xs (c, d)
go x []     r = (x, 0, r)
go x (y:ys) r = let !z = x + y; !r' = swap' r in go z ys r'

Compiled, both versions end up about 2 times faster than

foo x []     = (x, 0)
foo x (y:xs) = let !z = x + y in swap (foo z xs)

on foo 0 [0..1000000].
```