I'm trying to write my own List.partition function for F# practice. Here's my first (naive) attempt:
let rec mypartition_naive func list =
match list with
| [] -> ([],[])
| head::tail ->
let (h1,h2) = mypartition_naive func tail
if func head
then (head::h1,h2)
else (h1,head::h2)
This works, but it's not tail-recursive. I put together a second attempt that uses an accumulator to become tail-recursive:
let mypartition_accumulator func list =
let rec helper acc listinner =
match listinner with
| head::tail ->
let a,b = acc
let newacc = if func head then (head::a,b) else (a,head::b)
helper newacc tail
| _ -> acc
helper ([],[]) list
Strictly speaking, this works: it partitions the list. The problem is that this reverses the order of the lists. I get this:
let mylist = [1;2;3;4;5;6;7;8]
let partitioned = mypartition_accumulator (fun x -> x % 2 = 0) mynums
//partitioned is now ([8; 6; 4; 2], [7; 5; 3; 1])
//I want partitioned to be ([2; 4; 6; 8], [1; 3; 5; 7])
I think that I can use continuation passing to write a tail-recursive partition function that doesn't reverse the list elements, but I don't really understand continuation passing (and I've read a lot about it). How can I write partition using tail-recursive and keeping the list elements in order?