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

So, in Project AB, I have FileA.fs and FileB.fs. FileB uses definitions from FileA, and both FileA and FileB use definitions from Project C (written in C #).

In FileA.FS, I have:

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

... which works the way it should - I can run the whole file in F # -Interactive and thatโ€™s great.

In FileB.fs, my title is:

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

But when I run this (from FileB), I get an error:

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

According to the fsi.exe link, the #load directive reads the source file, compiles it and runs it. But it looks like this should be done without the COMPILED directive, because it does not see the ProjectAB declaration.

How to set headers so that I can run any file in F # -interactive?

Edit In response to latkin below, I created a script as the last file in the project, _TestScript.fsx. I removed all the precompiler materials from other files and set this as the header of the .fsx file:

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

When I run this interactively, it loads ProjectZ, FileA and FileB correctly for access in the interactive window.

However, in _TestScript.fsx I get short-term red lines and not intellisense for any of the functions / types from the referenced files (including the "open" statements).

Is there anything else I need to configure in the script file to make intellisense work? (The answer may be quite simple, as I have not used .fsx files before.)

+5
source share
1 answer

I donโ€™t think there is a way to do this smoothly. A few things to consider:

  • INTERACTIVE always determined when you process the fsi.exe file, regardless of whether you are .fsx, .fs, #load 'ed, whatever. COMPILED also always detected when you process the fsc.exe file. I can see how the quoted phrase from the documents may not make this crystal clear.

  • You can declare namespaces in fsi from the file #load 'ed

So, if you want your file to declare a namespace and work as a single file interactively, the namespace should be #ifdef 'ed out. But it also means that the namespace will be #ifdef 'out when the file #load ' ed ...

Perhaps you can get around this by conditionally declaring it to be a module, not a namespace. Or perhaps the creation of additional, more detailed definitions. It will be hard.

Trying to make the source files work properly as part of a compiled library and at the same time as single-file scripts is not easy, and I donโ€™t think the tool was designed with this scenario in mind. More common is that all of your library files behave like library files, and then use special stand-alone scripts that #load files they need. This leads to the fact that the driving code and the library code are separate, and everything is combined more cleanly.

+2
source

Source: https://habr.com/ru/post/1213483/


All Articles