I'm trying to learn how to estimate memory complexity of certain functions. And now I'm having a problem with one peculiar case.
So let's say we're building a function, something like this:
let f x = (fun x -> x :: [1;2;3]);;
And we're never calling this function, we're only composing it with another function at some point using this:
let compose f g x = f (g x);;
So the question is - how much space does f require before calling it and after calling compose on it? In order to make this question more general, when f builds n-sized array, but is not called, does it still take O(n) space or maybe it starts taking this space after calling it?
First note that
[1;2;3]is an immutable list, not an array. This has an impact on your space calculations because lists can share structure. Second, for simplicity I'll discuss things in terms of "conses", two-argument list constructors that take three words of storage - in reality OCaml programs are written in terms of constructors of many arities.Looking at
f, it generates one fresh cons per invocation, and references a list containing three constant conses. Assuming that constant conses are allocated statically (withocamloptthey are) we can use these observations to write an rough equation for space usage."Reachable result" means a value that is produced by
fand still visible within the program. Unreachable parts are ignored as the GC will reclaim them.When making this sort of estimation, make sure you understand that a cons is constant when all of its parts are constant (and no part is mutable). If the tail of a cons is a list with any non-constant part, then the cons is non-constant.
That is, in the following
there are no constant conses - all four will be allocated fresh each time through
f.