I have a F # function that returns a list of numbers starting at 0 in the skip pattern n, selects n, skips n, selects n ... to the limit. For example, this function for input 2 will return [2, 3, 6, 7, 10, 11...] .
I initially implemented this as a tailless function, as shown below:
let rec indicesForStep start blockSize maxSize = match start with | i when i > maxSize -> [] | _ -> [for j in start .. ((min (start + blockSize) maxSize) - 1) -> j] @ indicesForStep (start + 2 * blockSize) blockSize maxSize
Thinking that tail recursion is desirable, I reimplemented it using the battery list as follows:
let indicesForStepTail start blockSize maxSize = let rec indicesForStepInternal istart accumList = match istart with | i when i > maxSize -> accumList | _ -> indicesForStepInternal (istart + 2 * blockSize) (accumList @ [for j in istart .. ((min (istart + blockSize) maxSize) - 1) -> j]) indicesForStepInternal start []
However, when I run this in fsi in Mono with parameters 1, 1 and 20 000 (ie it should return [1, 3, 5, 7...] up to 20 000), the tail recursive version is much slower than the first version ( 12 seconds compared to sub-second).
Why is the tail recursive version slower? Is it because of list concatenation? Is this compiler optimization? Did I really implement its tail recursively?
It also seems to me that I should use higher order functions for this, but I'm not sure how to do it.