考虑一个像下面这样的haskell-expression:(简单的例子,不要告诉我明显的方法是什么!;)
toBits :: Integral a => a -> [Bool]
toBits 0 = []
toBits n = x : toBits m where
(m,y) = n `divMod` 2
x = y /= 0
因为这个函数不是尾递归的,所以也可以这样写:
toBits :: Integral a => a -> [Bool]
toBits = toBits' [] where
toBits' l 0 = l
toBits' l n = toBits (x : l) m where
(m,y) = n `divMod` 2
x = y /= 0
(我希望这个表达没有错)
我想问的是,这些解决方案中哪一个更好。第一个的优点是,它可以很容易地进行部分评估(因为 Haskell:
不需要在第一个处停止。),但第二个解决方案(显然)是尾递归的,但在我看来,它需要被完全评估直到你能拿出一些东西。
这个的背景是我的 Brainfuck 解析器,(见我的优化问题),它的实现非常丑陋(各种reverse
指令......哦),但可以很容易地在第一个实现 - 我们称之为“半尾递归”方式.