performance - F# efficiency implications of passing large data structures between functions -
how f# pass data caller function called function? make copy of data before handing on or pass pointer? think latter want make sure. on related note, there performance implications of following 2 f# code styles.
let somefunction e = 1//pretend complicated function let someotherfunction e = 2//pretend complicated function let foo f largelist= list.map (fun elem -> f elem) let bar largelist = largelist |> foo somefunction |> foo someotherfunction let bar2 largelist = let foo2 f f2 = largelist |> list.map (fun elem -> f elem) |> list.map (fun elem -> f2 elem) foo2 somefunction someotherfunction
would expect bar have different performance bar2? if not, there situations should aware of make difference?
the short answer:
no. entire list not copied, reference is.
the long answer:
in f# (just in c#) both value , reference types can passed either value or reference.
both value types , reference types are, default, passed value.
in case of value types (structs) means you'll passing around copy of entire data structure.
in case of reference types (classes, discriminated unions, records, etc.) means the reference passed value. not mean entire data structure copied, means
int
/int64
references data structure copied.
if you're working mutable data structures, e.g. resizearray<'t>
(.net list<'t>
) classes, passing references value have implications. perhaps function you've passed adds elements list, example? such update apply data structure referenced both locations. since question uses immutable f# list though, don't have worry this!
you can pass value/reference types reference, more detail see: https://msdn.microsoft.com/en-us/library/dd233213.aspx#anchor_4
f# list implemented singly linked list, means access head , prepend operations o(1). these data structures memory efficient because when prepend element list need store new value , reference rest of list.
so can see how works, such data structure can implemented this:
type examplelist<'t> = |empty |cons of 't * list<'t>
additional information:
list.map
eagerly evaluated meaning every time call it, new list created. if use seq.map
(f# list implements ienumerable<'t>
interface), lazily evaluated, can evaluate both map operations in enumeration of list.
largelist |> seq.map (fun elem -> f elem) |> seq.map (fun elem -> f2 elem) |> list.ofseq
this lot more efficient large lists because involves allocating 1 new list of results, rather two.
Comments
Post a Comment