简体   繁体   English

跨F#.fsx文件共享类型

[英]Sharing types across F# .fsx files

Is there a way to share types across fsx files? 有没有办法在fsx文件之间共享类型?

When using #load to load the same file containing a type from multiple FSX files they seem to be prefixed into a different FS_00xx namespace each time, which means you can't pass them around. 当使用#load从多个FSX文件中加载包含类型的同一文件时,它们似乎每次都被前缀为不同的FS_00xx命名空间,这意味着您无法将它们传递出去。

Are there any ways around this behaviour without resorting to compiling into an assembly? 有没有解决此问题的方法,而不必诉诸于汇编?

As for 至于

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

[.fsx files are] used to include informal testing code in F# without adding the test code to your application, and without creating a separate project for it. [.fsx文件]用于在F#中包含非正式测试代码,而无需将测试代码添加到您的应用程序中,也无需为其创建单独的项目。 By default, script files are not included in the build of a project even when they are part of a project. 默认情况下,脚本文件不包含在项目的构建中,即使它们是项目的一部分也是如此。

This means that if you have a project with enough structure to be having such dependency problems, you should not use .fsx files, instead write modules/namespaces using .fs files. 这意味着,如果你有足够的结构的项目是具有这样的依赖问题,你不应该使用.fsx文件,而不是写模块/命名空间使用.fs文件。 That is, you really should compile them types into an assembly. 也就是说,您确实应该将它们的类型编译为程序集。

The f# interactive interpreter generates assembly for each loaded files. f#交互式解释器为每个加载的文件生成程序集。 If you load a file twice, the bytecode is generated twice, and the types are different even if they have the same definition and the same name. 如果两次加载文件,字节码将生成两次,并且即使它们具有相同的定义和名称,它们的类型也会不同。 This means that there is no way for you to share types between two .fsx files, unless one of them includes the other . 这意味着您无法在两个.fsx文件之间共享类型,除非其中一个包含另一个

When you #load a file which has the same types as ones already present in your environment, the f# interactive interpreter can use two different strategy: #load加载与环境中已经存在的文件类型相同的文件时,f#交互式解释器可以使用两种不同的策略:

  1. refuse to load the file if conflicts with existing names arises (complaining that some stuff is already defined) 如果与现有名称发生冲突,则拒绝加载文件(说明已经定义了一些东西)
  2. put the names in FS_00xx namespace (so that they are actually different types from the ones you already loaded), eventually open ing the resulting namespace so that names are available from interactive session. 将名称放在FS_00xx命名空间中(以便它们实际上与已加载的名称类型不同),最终open结果名称空间,以便从交互式会话中获得名称。

Since fsx files are supposed to be used as informal test it is more user-friendly to use the second approach (there are also technical reason for which the second approach is used, mainly dependent on .net VM type system, and the fact that existing types cannot be changed at runtime). 由于fsx文件应被用作非正式测试,因此使用第二种方法更为用户友好(也存在使用第二种方法的技术原因,主要取决于.net VM类型系统,以及现有的类型不能在运行时更改)。

[ Note: This is a more specific answer to a more specific question that is a duplicate of this one.] [ 注意:这是对特定问题的更具体答案,该问题是该问题的重复。]

I don't think there is a nice and easy solution for this. 我认为没有一个很好且简单的解决方案。 The one solution I have been using in some projects (like the F# snippets web site ) is to have only one top-level fsx file that loads a number of fs files. 我在某些项目(例如F#代码段网站 )中一直使用的一种解决方案是,只有一个顶级fsx文件可以加载多个fs文件。 For example, see app.fsx . 例如,请参阅app.fsx

So, you would have common.fs , intMapper.fs and stringMapper.fs that would be loaded from caller.fsx as follows: 因此,您将具有从caller.fsx加载的common.fsintMapper.fsstringMapper.fs ,如下所示:

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

Inside stringMapper.fs and intMapper.fs , you do not load common.fs . stringMapper.fsintMapper.fs内部,您不会加载common.fs The common types will be loaded by caller.fsx before, so things will work. 常见类型将在之前由caller.fsx加载,因此一切正常。

The only issue with this is that intMapper.fs now isn't a standalone script file - and if you want to get autocomplete in an editor, you need to add a fsproj file that specifies the file order. 唯一的问题是intMapper.fs现在不是独立的脚本文件-如果要在编辑器中自动完成,则需要添加一个fsproj文件来指定文件顺序。 In F# snippets project, there is a project file which specifies the order in whch the editor should see and load the files. 在F#代码段项目中,有一个项目文件 ,指定编辑器应查看并加载文件的顺序。

Have all the #load and #open directives in the file you actually run from fsi.exe (C in the example below), and make sure the loaded files themselves do not #load their own dependencies: 在实际上从fsi.exe运行的文件中拥有所有#load#open指令(在下面的示例中为C),并确保加载的文件本身不会#load自己的依赖项:

Files A.fsx, B.fsx, C.fsx. 文件A.fsx,B.fsx,C.fsx。 B depends on A. C depends on B and A. B取决于A。C取决于B和A。

B contains B包含

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

C contains C包含

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

Unfortunately this then makes all the files hard to edit from Visual Studio - the editor doesn't know about their dependencies and shows all sorts of errors. 不幸的是,这使得所有文件都难以从Visual Studio中进行编辑-编辑器不知道它们的依赖性,并显示各种错误。

Therefore this is a bit of a hack, and the recommended way seems to be to have a single .fsx file and compile everything else into a .dll : 因此,这有点麻烦,建议的方法似乎是使用一个.fsx文件,然后将其他所有文件编译成.dll:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM