【发布时间】:2012-10-20 16:12:48
【问题描述】:
递归函数:
let rec listMerge (l1 : 'a list) (l2 : 'a list) =
if l1.IsEmpty then l2
elif l2.IsEmpty then l1
else l1.Head :: l2.Head :: listMerge l1.Tail l2.Tail
现在,除非我很高兴地弄错了,否则这实际上并没有执行尾调用,如果不考虑 :: 是右关联的话,它可能看起来像这样。
然后,我的印象(从我读过的东西,但现在找不到)可以通过使用额外的 fun 或其他东西轻松地将其转换为尾递归。
那么,有可能吗?代码?
我的回答:所以,这就是我更改功能的方式,感谢以下答案:
let listMerge l1 l2 =
let rec mergeLoop (l1 : 'a list) (l2 : 'a list) acc =
if l1.IsEmpty then (List.rev acc) @ l2
elif l2.IsEmpty then (List.rev acc) @ l1
else mergeLoop l1.Tail l2.Tail (l2.Head :: l1.Head :: acc)
mergeLoop l1 l2 []
【问题讨论】:
-
我建议您阅读有关模式匹配的内容。它会让你的同事更具可读性和简洁性。
-
如果你的意思是
match,我也有使用它的版本,虽然我认为这个更具可读性,但大声朗读几乎是简单的英语......虽然IL完全不同,我我想知道我是否应该发布另一个问题,询问哪个更有效。 -
“我想知道我是否应该发布另一个问题,询问哪个更有效”。您在此处编写的代码非常糟糕:不安全且速度慢。
-
@hyde “不安全怎么办?”您正在使用
Head和Tail函数,当您可以使用模式匹配让编译器证明您的代码在这方面的正确性时,它们会引发异常。 -
@hyde 如果存在
match抛出MatchFailureException的风险,那么编译器将发出警告。在这种情况下,编译器证明match永远不会抛出异常,因此您在编译时就知道您的代码永远不会以这种方式失败。
标签: function recursion f# functional-programming tail-recursion