如何让两种方法相互呼叫?

时间:2009-03-25 07:56:26

标签: f# mutual-recursion

我对如何让两种方法相互呼叫感到有点困惑(即A()呼叫B()B()呼叫A())。似乎F#只在代码中遇到它后“看到”该方法,所以如果它没有,它只是说值或构造函数尚未被定义

我错过了一些非常基本的东西吗?

4 个答案:

答案 0 :(得分:43)

'让rec ......和......'是你寻求的语法。

let rec F() = 
    G()
and G() =
    F()

另见Adventures in F# Co-Recursion

答案 1 :(得分:21)

由于问题是关于方法,而Brian的答案是关于函数的,可能有必要指出你可以对类型使用类似的语法:

type A() =
    let b = new B()
    member x.MethodA() = b.MethodB()
and B() =
    member x.MethodB() = ()

另请注意,默认情况下成员是'let rec'(实际上我认为它们不能递归)。

答案 2 :(得分:5)

F#4.1介绍mutually recursive modules and namespaces

这些是and关键字的替代方案。

module rec PingPong = // <------ rec keyword here.

    let pong() = 
        printfn "pong"
        ping() 

    let ping () = 
        printfn "ping"
        pong()

rec关键字定义了“允许所有包含的代码相互递归的模块和命名空间。”

答案 3 :(得分:4)

通过let

声明的函数
let rec a () = b ()
and b () = ()

这些是相互递归的函数

同一类型的方法

type T () =
    member t.A () = t.B()
    member t.B () = ()

这是微不足道的;它只是工作。 请注意Abel的评论。

不同类型的方法

type TypeA () =
    member t.A (b : TypeB) = b.B()

and TypeB () =
    member b.B () = ()

这使用相互递归类型的type ... and语法

备注

通常情况下,and仅在双向调用时使用。否则,最好重新排序声明,以便首先调用被调用的函数。对于类型推理和可读性来说,通常有助于避免循环依赖,并且不会将它们暗示在它们未被使用的地方。

我建议将问题编辑为要求一般的功能,或者要求不同的类型(在这种情况下,我会从这个答案中删除前两个案例)。方法通常被认为是函数的子集,这是一般的数学术语。但是,所有F#函数在技术上都是 CLI方法,因为它们是编译到的。因此,目前尚不清楚问题的要求,但我从接受的答案中假设它不仅要求方法,因为标题意味着。