示例:当使用Windows API获取Windows消息时,通常会在循环中实现。
我知道有可能创建一个将无限期地继续递归的函数。我希望这会导致堆栈溢出。
是无限循环错误的功能编程思维模式?
是操作系统或硬件界面的问题吗?
在我看来,它不像功能程序/ o。可以独自运行
我在编写功能程序方面有一点经验,但这一直困扰着我。 请分享您对这些问题的想法/见解
答案 0 :(得分:5)
如果你使用tail recursion,你实际上有一个迭代,就像for / while循环一样。因此,我猜你可以有一个无限循环而不会出现堆栈溢出。
对于你的问题: “无限循环错误的功能编程思维模式?” 也许这会有所帮助: - While or Tail Recursion in F#, what to use when?
答案 1 :(得分:4)
正如其他人发布的那样,tail recursions可能无限循环 。
E.g。 loop()
将有效地作为无限循环(在常量堆栈空间中)运行,因为编译器可以在最后优化loop
的尾递归调用。
let loop() = do {
println("foo")
loop()
}
但是
是无限循环错误的功能编程思维模式?
仍然有一点意义。考虑带有无限循环的Windows-API示例。这不是功能性的。记住 - 功能意味着在值中思考(和它们意味着什么)。因此,人们宁愿采用像[伪功能代码]
那样的基于反应/事件的方法 (onClick form1)
|> Event.subscribe (\pt-> do { print $ "I was clicked at " ++ (show pt) })
所以
在我看来,它不像功能程序/ o。可以独自运行
技术上错误 - 你可以实现无限循环 - 但这样做通常没有(功能)点。除了某种IO轮询之外,为什么还需要它呢?以纯函数方式转换值应该终止有意义。
答案 2 :(得分:1)
如果您的编译器识别它,您可以拥有无限tail recursion。一些语言,例如方案,要求编译器识别尾递归并为其分配没有堆栈空间。
编辑我不是故意不同意其他答案,但“无限”尾部递归循环是处理外部世界的常用习语。以下示例取自Real World Haskell,代表了成语。
mainloop :: Handle -> Handle -> IO ()
mainloop inh outh =
do ineof <- hIsEOF inh
if ineof
then return ()
else do inpStr <- hGetLine inh
hPutStrLn outh (map toUpper inpStr)
mainloop inh outh
我们基本上将外界视为stream。
答案 3 :(得分:0)
函数式编程中大多数(如果不是全部)“无限循环”的使用可以由co-recursion建模。到目前为止,其他答案都指向了一般的递归,但是不受限制地使用递归可以说是一种糟糕的方法,因为它可能导致结构不良的代码。
纯功能程序中的绝大多数代码应该写在整个子集中,即使用结构递归或共同递归(确保终止和进展)等模式,而不是回退到一般递归。希望未来版本的GHC将包括直接支持检测Haskell的一些完整子集并发出无法证明终止或进展的代码警告。