Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Errors when using #load #435

Closed
Pauan opened this issue Sep 26, 2016 · 9 comments
Closed

Errors when using #load #435

Pauan opened this issue Sep 26, 2016 · 9 comments

Comments

@Pauan
Copy link
Member

Pauan commented Sep 26, 2016

Consider these three files:

// foo.fsx
#load "bar.fsx"
#load "qux.fsx"

open Bar
open Qux

do
    printfn "%A" bar
    printfn "%A" qux
// bar.fsx
#load "qux.fsx"

open Qux

let bar = 10 + qux
// qux.fsx
let qux = 20

When I run fsharpi foo.fsx it correctly prints 30 and then 20

But when I run fable foo.fsx it gives the following error:

fable-compiler 0.6.7: Start compilation...
ERROR: F# project contains errors:
> The namespace or module 'Qux' is not defined (L3,5-L3,8) (bar.fsx)
> The value or constructor 'qux' is not defined (L5,15-L5,18) (bar.fsx)

This seems wrong: bar.fsx uses #load "qux.fsx" so it should have access to the Qux module.

If I rearrange the #load in foo.fsx so that it looks like this...

// foo.fsx
#load "qux.fsx"
#load "bar.fsx"

...

...then the problem goes away. But that makes it tricky to use nested #load, because you have to take into account the correct linear dependency order at every step.

I had tried putting all of the #load in the root file (foo.fsx), which works great for Fable. But when I'm editing the bar.fsx file, Ionide thinks that Qux isn't loaded (because bar.fsx doesn't have a #load "qux.fsx"), so it throws all kinds of errors.


Also, it seems like in fsharpi it actually evaluates the qux.fsx file twice. So #load is behaving like an #include in C. I prefer Fable's approach where each module is loaded once, even though it's incompatible with fsharpi

It seems like there's a tension between the correctness of using fsproj and the convenience of using fsx. That's a real shame, because I find fsproj to be a nightmare to use.

Related information

  • Fable Version 0.6.7
  • Mono Version 4.6.0
  • F# Version 4.0
  • Debian GNU/Linux 64-bit
@alfonsogarciacaro
Copy link
Member

Actually all your assumptions are correct. Fable's behaviour is indeed correct and in this case fsharpi just works in this case because it runs (and save into memory) every script when loading them.

Also, as you point out, it's possible to use an extra fsx script with the role of the project file but the inconvenience then is IDE support. I (and many people in the F# community) admit it's a pain to work with fsproj in a lightweight editor like Ionide. There's already work to create a more human friendly project file for F#. Unfortunately, there's no timeline for this, but Fable's need are not very demanding (basically an ordered list of files) so hopefully we can test a preview version of this new format with Fable very soon.

@Pauan
Copy link
Member Author

Pauan commented Sep 30, 2016

When you say "more human friendly project file", do you mean project.json? From what I understand, project.json has been discontinued and will be slowly phased out:

https://blogs.msdn.microsoft.com/dotnet/2016/05/23/changes-to-project-json/

https://blogs.msdn.microsoft.com/dotnet/2016/07/15/net-core-roadmap/

@alfonsogarciacaro
Copy link
Member

No, sorry. It's another file format made by the F# community. But they asked me not to disclose details until things are closer to alpha release, so I cannot say much more at the moment 😕

@Pauan
Copy link
Member Author

Pauan commented Sep 30, 2016

That's fine, I understand. I was very disappointed when I heard that project.json was discontinued, so I'm glad that F# is considering an alternative to fsproj.

P.S. Since this isn't a bug in Fable, I'm going to close this issue.

@Pauan Pauan closed this as completed Sep 30, 2016
@Pauan
Copy link
Member Author

Pauan commented Oct 19, 2016

Reopening because this is still an issue, and it's been decided for Fable to prefer fsx files instead of fsproj

@Pauan Pauan reopened this Oct 19, 2016
@Pauan
Copy link
Member Author

Pauan commented Oct 19, 2016

From what I understand, when fsharpi encounters #load "Foo.fsx", it immediately reads, compiles, and runs Foo.fsx. That means that it has a top-to-bottom depth-first load order (which is incidentally the same as the ES6 module load order).

I don't know what Fable does, but it's definitely not depth-first. So in order to solve this issue (and increase compatibility with fsharpi), here's what Fable needs to do:

When encountering #load "Foo.fsx", if Foo.fsx is already loaded, then it does nothing. Otherwise it immediately reads and compiles Foo.fsx. After Foo.fsx (and any sub-loads, recursively) are finished compiling, then it continues compiling the current file. This ensures depth-first load order.

There are other ways of implementing this, but the important part is that it is top-to-bottom and depth-first.

@alfonsogarciacaro
Copy link
Member

Hmm, I still think this is not a bug as it's according to F# specs. fsharpi and fsharpc are different. If you use the later I guess you'll get the same error as when using Fable. With fsharpi every #load replaces the previous one (this is because you can load new versions of the same file several times into F# interactive) so I think the #load "qux.fsx" in bar.fsx is overwriting the one in main.fsx.

However, the load resolution by the F# compiler first takes all the #r and #load directives in the other files, and then goes into the dependency tree discarding duplicated #loads, so that's probably the reason why the #load "qux.fsx" in bar.fsx has no effect when compiling the project from main.fsx. Maybe we could request a modification to fix this situation but I'm not sure how easy it would be. We already had a hard time to fix diamond dependencies 😉

In any case, please note this behaviour cannot be changed by Fable or Ionide but by the F# compiler itself, so we must be very careful that it doesn't affect other users.

@Pauan
Copy link
Member Author

Pauan commented Oct 19, 2016

You're right, fsharpc is broken too. 😞

I'm not really sure how to go about this: should you or I file a new issue in the FSharp.Compiler.Service repo?

Actually, this looks similar: fsharp/fsharp-compiler-docs#587 Maybe it's already fixed in a new version...?

@alfonsogarciacaro
Copy link
Member

alfonsogarciacaro commented Oct 19, 2016

I'll probably should just accept that .fsx files are not designed to build projects and give up on them, even if they're very convenient to work with using FCS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants