以下是用F#(类似于OCaml的功能语言)编写的程序
let bind f opt =
match opt with
| Some v -> f v
| None -> None
这是递归。
let example input =
let x = doSomething input
if x.IsSome then
let y = doSomethingElse (x.Value)
if y.IsSome then
let z = doAThirdThing (y.Value)
if z.IsSome then
let result = z.Value
Some result
else
None
else
None
else
None
这不是递归。是什么呢?
答案 0 :(得分:5)
这些都不是递归的。 F#中的递归函数使用rec
关键字。更重要的是,递归函数会自行调用。我没有看到example
中的任何地方使用了example
。我没有看到bind
中的任何地方使用了bind
。这些只是功能。绑定之所以特别,是因为它被用于影响控制流的许多模式和技术中。您的示例函数也是如此,输入确实决定了控制流程。有时将这种技术称为“面向铁路的编程”或ROP,其中您拥有满意或“正确”或“某些”路径以及“失败”或“左侧”或“无”路径。有时人们使用Result类型来捕获有关左路径的其他详细信息。
作为有趣的历史轶事,长期留在西方文化中意味着邪恶或堕落,因为左手用于个人卫生。
https://fsharpforfunandprofit.com/rop/
https://en.wikipedia.org/wiki/Bias_against_left-handed_people
答案 1 :(得分:2)
该示例与递归无关。
第一段代码是“绑定”的实现-函数编程中常见模式的一部分。
它接受带有签名f
和类型(a->Option<'b>)
的值opt
的函数Option<'a>
。如果opt的值(opt
等于Some v
),则将函数f应用于opt的值。 (因此返回None
或Some b
)。如果opt没有值(等于None
),则返回None
。
第二个示例看起来像一个示例,该示例说明了如何在不使用“绑定”的情况下编写代码。
使用第一个示例中的bind函数,第二个示例可以写得更清楚:
let example input =
input
|> doSomething
|> bind doSomethingElse
|> bind doAThirdThing