如何在所有情况下都使该F#函数尾部递归?

时间:2018-12-22 22:48:36

标签: recursion f#

我一直在努力解决今年的F#代码问世问题,以此来提高我的语言能力。我为Day 8, Part 1提出了以下解决方案:

namespace AdventOfCode2018.Core

module Day8 =

    let calculatePart1 input = 
        let rec take numberToTake numberTaken taken remaining =
            if numberTaken = numberToTake || List.isEmpty remaining then
                taken, remaining
            else
                take numberToTake (numberTaken + 1) 
                    (List.head remaining :: taken) (List.tail remaining)

        let rec calculate input sum depth maxDepth =
            let quantityOfChildNodes, quantityOfMetadata, remaining = 
                match input with
                | qc :: qm :: tl -> qc, qm, tl
                | _ -> 0, 0, []
            let input, sum = 
                match quantityOfChildNodes with 
                | 0 -> remaining, sum
                | q -> calculate remaining sum 1 q
            let metadata, remaining = take quantityOfMetadata 0 [] input
            let sum = sum + List.sum metadata
            if depth = maxDepth then remaining, sum
            else calculate remaining sum (depth + 1) maxDepth

        calculate input 0 0 1 |> snd

我的代码为该问题提供了正确的解决方案,并且似乎可以足够快地运行(使用i7机器上的我的拼图输入13ms)。但是,在调试代码时,我注意到它不是尾递归的。 calculate中的第一个递归调用将生成一个新的堆栈帧。函数末尾的第二个递归调用没有。我确定写第一个调用必须是尾递归的,但我不确定怎么做。

0 个答案:

没有答案