functional-programming


Calculating Big-O time and space complexity for functional languages


I'm thinking of using Ocaml for technical interviews in the future. However, I'm not sure how to calculate time and space complexity for functional languages. What are the basic runtimes for the basic higher level functions like map, reduce, and filter, and how do I calculate runtime and space complexity in general?
The time complexity of persistent recursive implementations is easy to infer directly from the implementation. In this case, the recursive definition maps directly to the recurrence relation. Consider the List.map function as it is implemented in the Standard Library:
let rec map f = function
| [] -> []
| a::l -> f a :: map f l
The complexity is map(N) = 1 + map (N-1) thus it is O(N).
Speaking of the space complexity it is not always that obvious, as it requires an understanding of tail-calls and a skill to see the allocations. The general rule is that in OCaml native integers, characters, and constructors without arguments do no allocate the heap memory, everything else is allocated in the heap and is boxed. All non-tail calls create a stack frame and thus consume the stack space. In our case, the complexity of the map in the stack domain is O(N), as it makes N non-tail calls. The heap-complexity is also O(N) as the :: operator is invoked N times.
Another place, where space is consumed are closures. If a function has at least one free variable (i.e., a variable that is not bound to function parameters and is not in the global scope), then a functional object called closure is created, that contains a pointer to the code and a pointer to each free variable (also called the captured variable).
For example, consider the following function:
let rec rsum = function
| [] -> 0
| x :: xs ->
List.fold_left (fun y -> x + y) 0 xs + rsum xs
For each element of a list, this function computes a sum this element, with all consecutive elements. The naive implementation above is O(N) in the stack (as each step has two non-tail calls), O(N) in the heap size, as each step constructs a new closure (unless the compiler is clever enough to optimize it). Finally, it is O(N^2) in the time domain (rsum(N) = (N-1) + rsum(N-1)).
However, it brings a question - should we take into account a garbage, that is produced by a computation? I.e., those values, that were allocated, during the computation, but are not referenced by it. Or those values, that are referenced only during a step, as in this case. So it all depends on the model of computation that you chose. If you will choose a reference counting GC, then the example above is definitely O(1) in the heap size.
Hope this will give some insights. Feel free to ask questions, if something is not clear.

Related Links

Erlang determine if record has a field
List option to list in OCaml
Some questions when reading “Why functional programming matters”
How to find double quotation marks in ML
Splitting array in erlang
OCaml visitor pattern
Why is OCaml still reasonable fast while constantly creating new things?
How to write a simple while true loop in Erlang for a receive call
Would like to swap elements in programming [closed]
OCaml : Simple function with conditionals doesn't work
NetLogo: How to implement `sentence-map` (aka `flatMap`)?
Erlang function calls - Why does it not work to call self() as a direct argument?
How to extract the instantiated variable in Isabelle?
Prove LISP is not functional [closed]
Why doesn't the set! function modify the original list in Scheme (r5rs)?
Differences between Derivable rules and Admissible rules?

Categories

HOME
xcode
adfs3.0
softlayer
hid
tcsh
informatica
moodle-api
vue-resource
elk-stack
apache-kafka-connect
navigation
minecraft
reportviewer
spring-security-oauth2
yeoman-generator-angular
scrape
tomcat8
pickle
wsf
bsd
web-analytics
substring
ini
exchange-server-2010
ratio
firemonkey-style
nurbs
unordered-multimap
cellular-network
python-appium
xenapp
location-services
publishing
python-2.x
reporting
rust-cargo
appcode
nest
android-canvas
java-stream
polyml
xerces-c
django-smart-selects
text-decorations
widestring
praat
grunt-contrib-watch
jacoco-maven-plugin
distributed-caching
hypothesis-test
realstudio
webvtt
swiperefreshlayout
dynamics-crm-4
word-2016
nrf51
oracle-fusion-apps
data-management
xcode8-beta4
openseadragon
wolfram-language
highlighting
frame-grab
netdatacontractserializer
hmisc
google-gdk
embeddedwebserver
gflags
sql-processor
flurry-analytics
qt5.4
distributed-r
jini
commenting
lync-2010
django-sites
iosched
boinc
flv
unicoins
jbox2d
donut-chart
django-filebrowser
dojo-1.9
simplecov
tridion-2011
viewpagerindicator
dynamic-c
delphi-prism
page-curl
jquery-1.4
turbine
gaelyk
aggregator
resharper-5.0
zend-test
ppc
autobench

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile