是否可以定义彼此依赖并在分离文件中定义的类型?
-
09-10-2019 - |
题
我正在尝试实现具有扩展解析功能的库。我决定使用FSYACC,因为我从大学中知道了。不幸的是,我遇到了以下问题。
我为我的语法校长定义了一堂课(头)并将其实现放在一个文件中。然后,我将解析器定义为:
...
%start head
%type <Head> head
...
FSYACC生成渗透模块(解析器)。为了成功,必须按以下顺序进行编译: Head.fs
Parser.fs
为了使此库类似于您在.NET中可以找到的库,我想添加静态 解析 方法 头. 。不幸的是我需要利用 解析器 模块。
我知道这样 类型依赖项 可以用'和'运算符,但仅适用于一个文件中定义的类型。
还有其他方法可以创建类型即使在单独的文件中彼此依赖的类型? 我一直在寻找像C/C ++中的声明/实施分离机制,但我找不到任何东西。
解决方案
简短答案:否。在F#2.0中的多个文件中,无法进行相互递归的实体。 (这是我们计划在该语言的下一个版本中解决的问题。)
您可以使用间接和突变点以多种方式解决此问题。例如,您的头类型可能具有静态的“初始Zeparser”方法,该方法将函数值戳入可变的全局变量中,然后在Head中定义的静态解析方法可以通过该可变的全局调用,并且在实际定义了解析器之后,它将可以去调用initializeparser以戳价。
其他提示
我希望这是可能的。在阅读Brian的答复后,我开始寻找合适的解决方法。我不想强迫图书馆用户调用任何初始化方法。因此,我想出了一些不同的东西。
如果编译器无法在编译时解决依赖项,我可以在运行时自行完成。这是我的DePencendCiesResolver的定义
module DependenciesResolver =
let GetMethod(_type, _method) =
lazy (
let a = System.Reflection.Assembly.GetExecutingAssembly()
let t = a.GetType(_type)
t.GetMethod(_method)
)
和分离文件中定义的类的示例:
A.fs
namespace MutualRecursion
type A() =
static member _b = DependenciesResolver.GetMethod("MutualRecursion.B", "b")
static member b() = A._b.Value.Invoke(null, [||])
B.FS
nameespace MutualRecursion
type B =
static member b() =
printf "Called b()"
汇编顺序为:A.FS B.FS
您不能使用第三个文件在这两个文件之后编译并使用新方法扩展头部的第三文件?
我会做类似以下操作的事情(我怀疑Brian提出的大致是)。请注意 用户 不必进行任何棘手的初始化 - 类型本身都知道如何“打结”。
head.fs
type IParser =
abstract Parse : string -> int // or whatever
...
type Head() =
static let mutable parser = Unchecked.defaultof<IParser>
static member internal SetParser p = parser <- p
member x.DoSomethingCool() =
let i = parser.Parse("something to parse")
...
Parser.fs
type Parser private () =
static do
Head.SetParser (Parser())
interface IParser with
member x.Parse s = 0
...