foldl is tail recursive, so how come foldr runs faster than foldl?

后端 未结 7 1382
無奈伤痛
無奈伤痛 2020-11-27 10:42

I wanted to test foldl vs foldr. From what I\'ve seen you should use foldl over foldr when ever you can due to tail reccursion optimization.

This makes sense. Howeve

7条回答
  •  再見小時候
    2020-11-27 11:15

    For a, the [0.. 100000] list needs to be expanded right away so that foldr can start with the last element. Then as it folds things together, the intermediate results are

    [100000]
    [99999, 100000]
    [99998, 99999, 100000]
    ...
    [0.. 100000] -- i.e., the original list
    

    Because nobody is allowed to change this list value (Haskell is a pure functional language), the compiler is free to reuse the value. The intermediate values, like [99999, 100000] can even be simply pointers into the expanded [0.. 100000] list instead of separate lists.

    For b, look at the intermediate values:

    [0]
    [0, 1]
    [0, 1, 2]
    ...
    [0, 1, ..., 99999]
    [0.. 100000]
    

    Each of those intermediate lists can't be reused, because if you change the end of the list then you've changed any other values that point to it. So you're creating a bunch of extra lists that take time to build in memory. So in this case you spend a lot more time allocating and filling in these lists that are intermediate values.

    Since you're just making a copy of the list, a runs faster because it starts by expanding the full list and then just keeps moving a pointer from the back of the list to the front.

提交回复
热议问题