I have some experience with FP and I found this function online which splits a list in two halves:
let split l = let n = List.length l in let rec splitAt k l = match k, l with | 0, _ -> [], l | _, [] -> [], [] | _, x::xs -> let l, r = splitAt (k-1) xs in x::l, r in splitAt (n/2) l
It works and I can see why but it seems a little strange in my mind. If someone had asked me to write a function which splits a list this what I would write:
let split2 l = let n = List.length l in let rec splitAt k acc l = if k=0 then (List.rev acc, l) else match l with | [] -> [], [] | h::t -> splitAt (k-1) (h::acc) t in splitAt (n/2) [] l
I think, if someone had given me the second function without its name it would be 100% clear immediately after I read it, but the first function seemed a tad more difficult to understand at first.
So my question is which is better, in terms of functional-style/OCaml best practices?
Disclaimer: I am talking about the essence of these functions (the logic with which they implement the list splitting), not syntax things (e.g. the use of if-then-else in my code instead of a pattern-matching)