As I mentioned in a recent SO question, I'm learning F# by going through the Project Euler problems.
I now have a functioning answer to Problem 3 that looks like this:
let rec findLargestPrimeFactor p n =
if n = 1L then p
else
if n % p = 0L then findLargestPrimeFactor p (n/p)
else findLargestPrimeFactor (p + 2L) n
let result = findLargestPrimeFactor 3L 600851475143L
However, since there are 2 execution paths that can lead to a different call to findLargestPrimeFactor, I'm not sure it can be optimized for tail recursion. So I came up with this instead:
let rec findLargestPrimeFactor p n =
if n = 1L then p
else
let (p', n') = if n % p = 0L then (p, (n/p)) else (p + 2L, n)
findLargestPrimeFactor p' n'
let result = findLargestPrimeFactor 3L 600851475143L
Since there's only one path that leads to a tail call to findLargestPrimeFactor, I figure it is indeed going to be optimized for tail recursion.
So my questions:
- Can the first implementation be optimized for tail recursion even if there are two distinct recursive calls?
- If both versions can be optimized for tail recursion, is there one better (more "functional", faster, etc) than the other?