跟踪:调试简单阶乘函数(使用累加器)



所以我浏览了这个视频(见4:07(,注意到所描述的函数实际上并没有正确计算阶乘(它似乎从未乘以2(。我通过将n <= 1更改为n <= 0来修复函数本身,但我似乎不明白为什么原始函数不起作用。

然后,我决定第一次使用跟踪进行Haskell调试,结果让我更加困惑。这是我现在使用的完整代码:

factorial n = auxiliaryFunction n 1
where
auxiliaryFunction n accumulator | trace ("n:" ++ show(n) ++ " n*acc: " ++ show (n*accumulator)) False = undefined
| n <= 1 = 1
| otherwise = auxiliaryFunction (n-1) n*accumulator 

该输出:

n:1 n*acc: 5
n:5 n*acc: 20
n:4 n*acc: 12
n:3 n*acc: 6
n:2 n*acc: 2

首先,为什么n=1首先通过跟踪得到输出?不是应该是n=5吗?有趣的是,使用n <= 0 = 1时也会发生同样的情况,输出如下:

n:1 n*acc: 5
n:5 n*acc: 20
n:4 n*acc: 12
n:3 n*acc: 6
n:2 n*acc: 2
n:1 n*acc: 0

这似乎更有意义,因为n=1的情况是在所有其他情况之后进行评估的(但也在开始时?(,这使得上次调用的累积值2可以适当地相乘并添加到函数的最终输出中。我好像有点不对劲。

我也觉得我错过了一些关于价值观如何累积的关键内容。如果这个问题看起来有点像官样文章,我很抱歉,但我只是感到困惑。

您应该在n <= 1的情况下返回累加器,还应该放上类似auxiliaryFunction (n-1) (n*accumulator)的括号:通过写入auxiliaryFunction (n-1) n*accumulator,这被解释为(auxiliaryFunction (n-1) n)*accumulator

factorial :: Integral i => i -> i
factorial n = go n 1
where go n acc
| n <= 1 =acc
| otherwise = go (n-1)(n*acc)

最新更新