我有些困惑如何让两个方法相互调用(例如,让A()
调用B()
,并使B()
调用A()
)。似乎 F# 只有在代码中遇到方法后才会“看到”它,因此如果没有遇到它,它就会显示“值或构造函数未定义”的错误信息。
我是否漏掉了一些非常基础的东西?
我有些困惑如何让两个方法相互调用(例如,让A()
调用B()
,并使B()
调用A()
)。似乎 F# 只有在代码中遇到方法后才会“看到”它,因此如果没有遇到它,它就会显示“值或构造函数未定义”的错误信息。
我是否漏掉了一些非常基础的东西?
因为问题是关于方法的,而Brian的答案是关于函数的,也许指出你可以使用类似的语法来定义类型会很有用:
type A() =
let b = new B()
member x.MethodA() = b.MethodB()
and B() =
member x.MethodB() = ()
需要注意的是,默认情况下成员被视为 'let rec'(事实上,我认为它们不能不递归)。
F# 4.1 引入了相互递归模块和命名空间,这是 and
关键字的一种替代方案。
module rec PingPong = // <------ rec keyword here.
let pong() =
printfn "pong"
ping()
let ping () =
printfn "ping"
pong()
rec
关键字用于定义模块和命名空间,以“允许所有包含的代码相互递归调用”。
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方法,因为它们编译成这样。目前,不清楚问题正在询问什么,但我假设从已接受的答案中得知,它不仅仅要求方法,正如标题所示。
inline
和/或某些成员约束时,可能需要按顺序声明它们(即,反向引用将产生奇怪且难以诊断的错误)。请参见错误报告类型成员的顺序是相关的。 - Abel