Arrays are probably the most widely used data structure
in imperative programming languages, yet functional languages
typically only support arrays in a limited manner, or prohibit
them entirely. This is not too surprising, since most other
mutable data structures, such as
trees, have elegant immutable analogues in the functional world,
whereas arrays do not. Previous attempts at addressing the
problem have suffered from one of three weaknesses, either
that they don't support arrays as a persistent data
structure (unlike the functional analogues
of other imperative data structures), or that the range of
operations is too restrictive to
support some common array algorithms efficiently, or that they
have performance problems.
Our technique provides arrays as a true functional analogue of
imperative arrays with the
properties that functional programmers have come to expect
from their data structures. To
efficiently support array algorithms from the imperative world,
we provide O(1) operations for
single-threaded array use. Fully persistent array use can also
be provided at O(1) amortized
cost, provided that the algorithm satisfies a simple
requirement as to uniformity of access.
For those algorithms which do not access the array uniformly
or single-threadedly, array
reads or updates take at most O(log n)
amortized time, where n is the size of the array.
Experimental results indicate that the overheads of our
technique are acceptable in practice for many applications.