Dmi*_*ruk 34 f# mutual-recursion
关于如何让两个方法相互呼叫(即有A()
呼叫B()
和B()
呼叫A()
),我有点困惑.似乎F#只在代码中遇到它后"看到"该方法,所以如果它没有,它只是说值或构造函数尚未定义.
我错过了一些非常基本的东西吗?
Bri*_*ian 44
'让rec ......和......'是你寻求的语法.
let rec F() =
G()
and G() =
F()
Run Code Online (Sandbox Code Playgroud)
Kur*_*out 21
既然问题是关于方法的,而Brian的答案是关于函数的,那么指出你可以对类型使用类似的语法是有用的:
type A() =
let b = new B()
member x.MethodA() = b.MethodB()
and B() =
member x.MethodB() = ()
Run Code Online (Sandbox Code Playgroud)
另请注意,默认情况下成员是'let rec'(实际上我不认为它们不能递归).
let rec a () = b ()
and b () = ()
Run Code Online (Sandbox Code Playgroud)
这些是相互递归的函数。
type T () =
member t.A () = t.B()
member t.B () = ()
Run Code Online (Sandbox Code Playgroud)
这是微不足道的;它只是有效。不过请注意 Abel 的评论。
type TypeA () =
member t.A (b : TypeB) = b.B()
and TypeB () =
member b.B () = ()
Run Code Online (Sandbox Code Playgroud)
这使用了相互递归类型的type ... and
语法。
通常,and
仅当呼叫发生在两个方向时才使用。否则,最好对声明重新排序,以便被调用的函数排在最前面。它通常有助于类型推断和可读性,以避免循环依赖,并且不在不使用它们的地方暗示它们。
我建议编辑问题以要求一般的功能,或要求不同的类型(在这种情况下,我会从这个答案中删除前两种情况)。方法通常被认为是函数的子集,这是通用的数学术语。但是,所有 F# 函数在技术上都是CLI 方法,因为它们是编译成的。照原样,尚不清楚问题要求什么,但我从公认的答案中假设它不仅要求方法,正如标题所暗示的那样。
F#4.1引入了相互递归的模块和命名空间.
这些是and
关键字的替代品.
module rec PingPong = // <------ rec keyword here.
let pong() =
printfn "pong"
ping()
let ping () =
printfn "ping"
pong()
Run Code Online (Sandbox Code Playgroud)
该rec
关键字定义了"允许所有包含的代码相互递归"的模块和命名空间.