跨F#.fsx文件共享类型

时间:2014-06-18 12:04:32

标签: f#

有没有办法在fsx文件之间共享类型?

当使用#load从多个FSX文件加载包含类型的同一文件时,它们似乎每次都被添加到不同的FS_00xx命名空间中,这意味着您无法传递它们。

有没有办法绕过这种行为而不需要编译成程序集?

3 个答案:

答案 0 :(得分:9)

至于

http://msdn.microsoft.com/en-us/library/dd233169.aspx

  

[。fsx文件]用于在F#中包含非正式测试代码,而无需将测试代码添加到您的应用程序,也无需为其创建单独的项目。默认情况下,即使项目是项目的一部分,脚本文件也不会包含在项目的构建中。

这意味着如果您的项目具有足够的结构以存在此类依赖性问题,则不应使用.fsx文件,而应使用.fs文件编写模块/命名空间。也就是说,你真的应该将它们编译成一个程序集。

f#交互式解释器为每个加载的文件生成程序集。如果加载文件两次,则会生成两次字节码,即使它们具有相同的定义和相同的名称,类型也会不同。这意味着您无法在两个.fsx文件之间共享类型,除非其中一个包含其他

当您#load文件的类型与您环境中已存在的文件类型相同时,f#交互式解释器可以使用两种不同的策略:

  1. 如果出现与现有名称的冲突,则拒绝加载文件(抱怨某些内容已经定义)
  2. 将名称放在FS_00xx名称空间中(这样它们实际上与您已加载的名称不同),最终open生成的名称空间,以便可以从交互式会话中获得名称。
  3. 由于 fsx文件应该用作非正式测试,因此使用第二种方法更加用户友好(也有技术原因使用第二种方法,主要依赖于{ {1}} VM类型系统,以及在运行时无法更改现有类型的事实。

答案 1 :(得分:6)

[注意:这是more specific question的更具体的答案,与此重复。]

我不认为有一个很好的解决方案。我在一些项目中使用的一个解决方案(如the F# snippets web site)只有一个顶级fsx文件,可以加载大量fs个文件。例如,请参阅app.fsx

因此,您将common.fsintMapper.fsstringMapper.fscaller.fsx加载,如下所示:

#load "common.fs"
#load "stringMapper.fs"
#load "intMapper.fs"
open Common

stringMapper.fsintMapper.fs内,你加载common.fs。公共类型之前将由caller.fsx加载,因此事情将起作用。

唯一的问题是intMapper.fs现在不是独立的脚本文件 - 如果要在编辑器中获得自动完成功能,则需要添加一个fsproj文件来指定文件顺序。在F#snippets项目中,有a project file,它指定编辑器应该查看和加载文件的顺序。

答案 2 :(得分:1)

在您实际运行的文件中使用fsi.exe(以下示例中的C)中的所有#load#open指令,并确保加载的文件本身不是#load他们自己的依赖:

文件A.fsx,B.fsx,C.fsx。 B取决于A. C取决于B和A.

B包含

//adding the code below would cause the types defined in A to be loaded twice
//#load "A.fsx"
//#open A

C包含

#load "A.fsx"
#open A
#load "B.fsx"
#open B

不幸的是,这使得所有文件都很难从Visual Studio编辑 - 编辑器不知道它们的依赖关系并显示各种错误。

因此,这有点像黑客,推荐的方法似乎是拥有一个.fsx文件并将其他所有文件编译成.dll:

// file1.fsx
#r "MyAssembly.dll"
     

https://msdn.microsoft.com/en-us/library/dd233175.aspx