2

Does FSI deal well with multi module/file F# projects? Consider the following project:

module.fs:

module Xyz

let add x y = x + y

Program.fs:

module Program

open Xyz    
let result = add 1 2

selecting and running the last 2 lines of Program.fs will yield the following FSI error:

Program.fs: error FS0039: The namespace or module 'Xyz' is not defined

What is the problem here?


So, let's say I have the following project structure:

A.fs
B.fs
C.fs
D.fs
E.fs

I want to run some functions of E.fs. E.fs makes use of all the other .fs files, so I have one open for each one of them. If later on I want to also run some code from any one of the other files, I'll have to repeat the process fo any file that was not #loaded before.

From your suggestions, it seems like to make my E.fs file run on FSI I'll either have to create a separate .fsx file or have a separate

#if INTERACTIVE
#load "..."

for each module I'll use which is IMO quite redundant. Am I missing something here, or is this a clear violation of both KISS and DRY principles?

devoured elysium
  • 101,373
  • 131
  • 340
  • 557

4 Answers4

4

The error will be because you have not loaded the file - it works fine for me doing

 $ fsi --load:module.fs --load:Program.fs

Microsoft (R) F# 2.0 Interactive build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

[Loading /suphys/jpal8929/fsbug/module.fs
 Loading /suphys/jpal8929/fsbug/Program.fs]

namespace FSI_0002
  val add : int -> int -> int


namespace FSI_0002
  val result : int

> 
John Palmer
  • 25,356
  • 3
  • 48
  • 67
  • Ah, thanks. But isn't there something *easier*? I mean, let's say I have this huge file that opens 5, 6 modules. Better yet, imagine I have this big project where I want to run a couple of functions in file X, a couple of functions in file Y, etc from FSI. If I have to manually load every file each one of those files use it gets really easily tiresome. I guess there must be some other way of achieving this..? Unless F#'s purpose is nothing but single file "projects", I'm finding this extremely awkward. (I'm using FSI from Visual Studio, btw). – devoured elysium Aug 30 '11 at 07:17
  • @devoured - you can write a script.fsx file with contents `#load "module.fs";;` to easily load the files – John Palmer Aug 30 '11 at 10:01
  • The problem is that I don't see what is *easy* in the approach described. See the edit of my original post. – devoured elysium Aug 30 '11 at 10:56
  • @devoured The real problem is if you have many files, the order f\the files are included will have an effect on the ouput (consider 2 files which both define an add function). As a result Visual Studio cannot possibly do this in the correct order. An alternative is to compile everything to a dll/exe and then you can load the DLL with `#r...` which only needs 1 call per dll which could have multiple files – John Palmer Aug 30 '11 at 11:24
  • @devouredelysium if you use VSCode and install the Ionide-fsharp extension, you can select the "FSI: Generate script file..." options from the Ctrl+Shift+P menu, and that'll create an `fsx` file for you with all the correct `#r` and `#load` directives, that can be pretty handy. – Mark Vincze Jun 27 '17 at 21:33
3

There are a few options, some of them already mentioned by Brian and jpalmer, so I'll just try to summarize:

  • If you have just a few files, then you can "load" them, which means that the source gets sent to F# Interactive and is compiled in the FSI console. This approach is useful if you want to test a part of a larger project.

    To do this, you can either use --load:file.fs command line option or you can write #load "file.fs" in F# Interactive (or in a Script.fsx file that is sent to F# Interactive using --load). To manage more files, you can write a script Load.fsx that loads all the files you need.

  • If you have a larger project (e.g. a library) and want to use it or test it from F# Interactive, then you can compile the library using fsc.exe, reference it from F# Interactive and use its public types/functions from the console

    To do this, you can either use -r:MyLib.dll command line option, or you can write #r "MyLib.dll in F# Interactive (or in an fsx script file).

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
2

Are you aware of #load? Are you aware of #r (after compiling other code into a DLL)? http://msdn.microsoft.com/en-us/library/dd233175.aspx

Brian
  • 117,631
  • 17
  • 236
  • 300
0

Create an .fsx file that begins:

#load "module.fs" "Program.fs"

and run that from FSI first to get your code loaded.

J D
  • 48,105
  • 13
  • 171
  • 274