It is important to understand this in terms of two factors: mutation and sharing. You seem to be focusing on the aspect of mutation and seemingly ignoring sharing.
Take the standard list-append '@'; he copies left arg and shares right
So, yes, it’s true that you are losing efficiency by copying, but you will receive sharing accordingly. And therefore, if you streamline your data structures to maximize shared access, you will benefit from what you have lost due to the immutability caused by copying.
For the most part, this is “just happening.” However, sometimes you need to configure it.
A general example involving laziness in haskell:
ones = 1 : ones
this denotes an endless list of 1s [1,1,1,...] And the implementation can be expected to optimize it before the loop (pie chart)
+-----------+ | | V | +---------+ | | | | | 1 |-->---+ | | +---------+
However, when we generalize it to an infinite list of x-es
repeat x = x : repeat x
the implementation has more difficult time detecting a loop because the ones variable has now become a (recursive) call function repeat x
Change it to
repeat x = let repeat_x = x : repeat_x in repeat_x
and the cycle (i.e. sharing) is restored.
Rusi
source share