Recursion 为什么在F#中使用递归函数而不是'while true do'?
在观看Tomas Petricek(我想他知道他在说什么)的视频时,我看到了如下代码Recursion 为什么在F#中使用递归函数而不是'while true do'?,recursion,f#,functional-programming,Recursion,F#,Functional Programming,在观看Tomas Petricek(我想他知道他在说什么)的视频时,我看到了如下代码 let echo = MailboxProcessor<string>.Start(fun inbox -> async { while do true let! msg = inbox.Receive() printfn "Hello %s" msg }) 从复制的代码 这里的内部函数是递归的,在主函数声明结束之前,通过使用基值调用它
let echo =
MailboxProcessor<string>.Start(fun inbox ->
async {
while do true
let! msg = inbox.Receive()
printfn "Hello %s" msg
})
从复制的代码
这里的内部函数是递归的,在主函数声明结束之前,通过使用基值调用它来启动
现在我意识到,在第二种情况下,递归是一种将私有值传递给内部函数的简便方法,而不必使用可变的局部值,但是在这里使用递归而不是,而dotrue
?使用递归编写第一个代码段有什么好处吗
我发现非递归版本更容易阅读(当然是主观意见),这似乎是尽可能使用它的一个很好的理由。在许多情况下,它取决于您喜欢如何编写代码。就像你的例子一样。 可以编写递归的所有内容也可以使用循环编写,但有时像使用递归数据结构一样,使用递归样式编写更容易。 在大学里,我学到了递归编程,你只需要看看你的下一步,这是非常方便的 您可能对这个问题感兴趣,因为它进一步解释了我的答案:
谈到
邮箱处理器
具体来说,我认为选择取决于你到底在做什么。通常,您可以在循环或递归时始终使用
递归使使用不可变状态变得更容易,如果没有状态或使用可变状态,我发现while
循环更好。使用可变状态通常非常有用,因为MailboxProcessor
可以防止并发访问,并且可以将状态保持为本地状态,因此像Dictionary
(高效哈希表)这样的东西通常很有用
一般而言:
- 如果您不需要任何状态,我更喜欢
while
- 如果您有可变状态(如
字典
或大小数组
),我会选择而
- 如果您有一些不可变的状态(如函数列表或整数),那么递归就更好了
- 如果您的逻辑在多种操作模式之间切换,那么您可以将其编写为两个相互递归的函数,这对于循环来说是不可行的
在F#中用于
和,而
循环表达式缺少其他语言中常见的功能:
继续
-跳过循环的其余部分,然后从循环表达式的顶部重新启动
中断
-过早停止循环
如果您想要continue
和break
请不要像我刚开始做的那样,为while
循环编写一个非常复杂的测试表达式。相反,尾部递归是F#中的最佳答案:
有时,当您在寻找性能时,一个技巧是循环到0
(保存CPU寄存器)。不幸的是,F#为
循环代码生成的方式没有人们希望的那么好:
for i = 100 downto 0 do
printfn "Unfortunately this is not as efficient as it can be"
朝向0的尾部递归保存CPU寄存器
(不幸的是,F#编译器没有为尾部递归合并测试和循环指令,因此它没有达到预期的效果)谢谢,回复很好,链接也很有趣。我会接受托马斯的回答,因为他把选项说得更清楚了一点,但我也很感激你的回答。谢谢,这些要点说得很清楚。也谢谢你的精彩课程,请多做一些!
let vs : int [] = ...
let rec findPositiveNumberIndex i =
if i < vs.Length then
if vs.[i] > 0 then
Some i
else
findPositiveNumberIndex (i + 1)
else
None
match findPositiveNumberIndex 0 with
| Some i -> printfn "First positive number index: %d" i
| None -> printfn "No positive numbers found"
for i in 0..100 do
printfn "This is a fast loop"
for i in 0..2..100 do
printfn "This is a slow loop"
for i in 0L..100L do
printfn "This is a slow loop"
for i = 100 downto 0 do
printfn "Unfortunately this is not as efficient as it can be"