对于F#中的递归,在特殊情况下(仅是一个函数调用自身,或一组物理上相邻的函数相互调用),现有文档清楚地说明了如何执行此操作。

但是在通常情况下,不同模块中的一组函数需要相互调用,您该怎么做?

最佳答案

我认为F#中没有办法实现这一目标。通常可以用不需要这种方式来构造应用程序,因此,如果您描述了您的方案,则可能会得到一些有用的注释。

无论如何,有多种方法可以解决此问题-您可以声明一条记录或一个接口(interface)来保存需要从模块中导出的功能。接口(interface)也允许您导出多态函数,因此它们可能是更好的选择:

// Before the declaration of modules
type Module1Funcs =
  abstract Foo : int -> int
type Module2Funcs =
  abstract Bar : int -> int

然后,模块可以导出一个实现接口(interface)和函数的值,而该值要求另一个模块可以将其用作参数(或者可以将其存储为可变值)。
module Module1 =
  // Import functions from Module2 (needs to be initialized before using!)
  let mutable module2 = Unchecked.defaultof<Module2Funcs>

  // Sample function that references Module2
  let foo a = module2.Bar(a)

  // Export functions of the module
  let impl =
    { new Module1Funcs with
        member x.Foo(a) = foo a }

// Somewhere in the main function
Module1.module2 <- Module2.impl
Module2.module1 <- Module1.impl

初始化也可以使用Reflection自动完成,但这有点丑陋,但是如果您确实经常需要它,我可以想象为此开发一些可重用的库。

在许多情况下,这样做感觉很丑陋,对应用程序进行结构调整以避免递归引用是一种更好的方法(实际上,我发现面向对象编程中的类之间的递归引用常常很混乱)。但是,如果您确实需要这样的东西,那么使用接口(interface)/记录导出功能可能是唯一的选择。

关于f# - 模块之间的F#相互递归,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2904889/

10-11 22:52
查看更多