F# interactive - 当多个文件引用同一个程序集时如何使用预编译器指令?

F# interactive - how to use precompiler directives when multiple files reference the same assembly?

因此,在项目 AB 中我有 FileA.fs 和 FileB.fs。 FileB 使用 FileA 的定义,FileA 和 FileB 都使用项目 C(用 C# 编写)的定义。

在FileA.FS中,我有:

#if COMPILED
namespace ProjectAB
#else
#I "bin\debug"
#r "ProjectZ.dll"
#endif

...按预期方式工作 -- 我可以 运行 F#-Interactive 中的整个文件,这很棒。

在FileB.fs中,我的header是:

#if COMPILED
module ProjectAB.ModuleB
#else
#load "FileA.fs"
#I "bin\debug"
#r "ProjectZ.dll"
#endif

但是当我 运行 这个(来自 FileB)时,我得到错误:

FileA.fs(6,1): error FS0222: Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. 'namespace SomeNamespace.SubNamespace' or 'module SomeNamespace.SomeModule'. Only the last source file of an application may omit such a declaration.

根据 fsi.exe 参考,#load 指令 "Reads a source file, compiles it, and runs it"。但它似乎必须在没有定义 COMPILED 指令的情况下这样做,因为它没有看到 "namespace ProjectAB" 声明。

如何设置我的 header 以便我可以 运行 在 F#-interactive 中任一文件?

Edit 根据 latkin 在下面的回答,我创建了一个脚本作为项目中的最后一个文件,_TestScript.fsx。我从其他文件中删除了所有预编译器内容并将其设置为 .fsx 文件的 header:

#if INTERACTIVE
#I "bin\debug"
#r "ProjectZ.dll"
#load "FileA.fs"
#load "FileB.fs"
#endif

当我在交互式 运行 中执行此操作时,它会正确加载 ProjectZ、FileA 和 FileB 供我在交互式 window 中访问 window。

但是,在 _TestScript.fsx 中,我在引用文件(包括 "open" 语句)中的任何 functions/types 上看到了波浪形的红线并且没有任何智能感知。

是否需要在脚本文件中设置其他内容才能使智能感知正常工作? (答案可能很简单,因为我以前没有使用过 .fsx 文件。)

我认为没有办法顺利地做到这一点。需要考虑的几点:

  • INTERACTIVE 始终在您被 fsi.exe 处理时定义,无论您是 .fsx、.fs、#loaded 等等。 COMPILED 同样总是在你被 fsc.exe 处理时定义。我可以看出文档中引用的短语可能没有使这一点完全 crystal 清楚。

  • 您只能从 #load 编辑的文件

  • 中在 fsi 中声明名称空间

因此,如果您希望您的文件声明一个名称空间,并在交互中作为单个文件工作,则必须 #ifdef 删除名称空间。但这也意味着当文件被#load编辑时命名空间将被#ifdef编辑...

您可以通过有条件地将其声明为模块而不是名称空间来解决此问题。或者可能创建额外的、更细化的定义。这将是棘手的。

尝试让源文件作为已编译库的一部分并同时作为单文件脚本正常工作并不容易,而且我认为该工具在设计时并未考虑到这种情况。更常见的是让您的所有库文件纯粹作为库文件运行,然后使用专用的独立脚本,其中 #load 是他们需要的 .fs 文件。这使驱动代码和库代码保持分离,并且更干净地组合在一起。