Closed jkone27 closed 2 years ago
I could not repro this issue with information provided.
@jkone27: Would it be possible for you to narrow it down to a minimal sequence of steps that can reproduce this bug?
So far I got it down to a fairly small repro, four script files still needed:
A.fsx:
#load "Domain.fsx"
let a = Domain.T
B.fsx:
#load "Domain.fsx"
let b = Domain.T
Domain.fsx:
type T = T
Script.fsx:
#load "A.fsx"
#load "B.fsx"
A.a = B.b
~same error:
> dotnet fsi Script.fsx
Script.fsx(4,7): error FS0001: This expression was expected to have type
'FSI_0001.Domain.T'
but here has type
'FSI_0002.Domain.T'
This unfortunately seems to currently be by design for fsi
- each time a script is loaded it gets wrapped in a new outer namespace. It seems to have been this way since dotnet 5 at least, maybe forever.
Fixing this would significantly improve fsi
scripting story IMO, but it is more of a feature request that would have to be submitted as a proposal at fslang-suggestions. And it would have to account for both interactive sessions with fsi
and running a script with fsi ScriptName.fsx
as well as for a case when script file has changed in between loads. @jkone27 I encourage you to submit a suggestion there if you have time to write it up.
Sidenote: F# language specification describes how scripts should behave when compiled and that includes loading same script file multiple times:
Script files may add other signature, implementation, and script files to the list of sources by using the #load directive. Files are compiled in the same order that was passed to the compiler, except that each script is searched for #load directives and the loaded files are placed before the script, in the order they appear in the script. If a filename appears in more than one #load directive, the file is placed in the list only once, at the position it first appeared.
and in fact, when compiled with fsc.exe Script.fsx
, the code I pasted above runs without this type error. However, that's not even a suitable work around as far as I am concerned. And there's nothing about semantics of running scripts with fsi
in the spec.
I believe I've found a viable workaround:
In Script.fsx
replace multiple #load
s:
#load "Domain.fsx"
#load "Dto.fsx"
#load "Infrastructure.fsx"
with one:
#load "Domain.fsx" "Dto.fsx" "Infrastructure.fsx"
I am not yet convinced if this is always a feasible solution to these kinds of issues, but @jkone27, let me know if it works for you
Yes this workaround works! thanks a LOT 👍 💚
Please note the above is the correct approach
Closing as by-design.
Thanks, @abonie just suggesting also for new users, maybe the compiler error should make this design decision more explicit to the user, or suggest this option if there is a multiline load
#load
#load
--> compiler fail with
please replace multiline #load directives with a single load# directive in your script file ,
#load supports multiple scripts in the same line, example: `#load "first.fsx" "second.fsx"`
@jkone27 I believe there are subtleties about how those directives impact the evaluation, that would make such adjustment problematic, on top of backward compatibility.
Adjusting https://learn.microsoft.com/en-us/dotnet/fsharp/tools/fsharp-interactive/#f-interactive-directive-reference so it shows that several files can be loaded seems to be a good solution to make it explicit, what can be done with this directive.
I get this behaviour when referencing multiple scripts from different files
i have a single Domain.fsx which i load in multiple files and then open as open Domain
I am not sure why is not possible to load Domain, ionide in vscode shows no errors.
note: restarting ionide - closing/reopening vscode doesnt help