dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.93k stars 786 forks source link

Oddities with FSI package management #9270

Closed dsyme closed 4 years ago

dsyme commented 4 years ago

I'm just starting to use FSI package maangement and noticed a few things. I'll use this issue to document oddities or bugs as I notice them.

Delayed feedback on executing #r "nuget..."

  1. run dotnet artifacts\bin\fsi\Debug\netcoreapp3.0\fsi.exe /langversion:preview

  2. Type #r "nuget: FSharp.Data";;

Expected: some kind of feedback Actual: the feedback comes after your next non-nuget interaction, e.g. type 1+1;; and then you get a project loaded.

I think we could print FSharp.Data registered for nuget processing or something. Just so you know something happened.

Syntax differences with fsi and notebooks

In .NET Interactive Jupyter notebooks I do this for extra package sources:

#i "nuget: https://donsyme.pkgs.visualstudio.com/TorchSharp/_packaging/packages2/nuget/v3/index.json"
#r "nuget:libtorch-cpu,0.3.52118"
#r "nuget:TorchSharp,0.3.52118"

but in F# Interactive I do this:

#r "nuget:RestoreSources=https://donsyme.pkgs.visualstudio.com/TorchSharp/_packaging/packages2/nuget/v3/index.json"
#r "nuget:libtorch-cpu,0.3.52118"
#r "nuget:TorchSharp,0.3.52118"

Why the difference in the first line?

Native DLL not found

See this error: https://github.com/dotnet/interactive/issues/464

KevinRansom commented 4 years ago

@dsyme,

the lazy activation of #r "nuget: " has been it's behaviour since the very first prototype. The #r collects the arguments, but package resolve does not happen until code compilation happens.

notebook has a different and better experience because we run the resolve up in the host before we invoke fsi to execute the script.

I too prefer the notebook behavior and have on my personal backlog the desire to experiment how to reproduce this behavior in fsi.

dsyme commented 4 years ago

the lazy activation of #r "nuget: " has been it's behaviour since the very first prototype. The #r collects the arguments, but package resolve does not happen until code compilation happens.

My gut feeling is that the resolution should be forced by

Design notes:

  1. The ;; terminator in F# means "commit everything and do your thing". And I think the delayed accumulation of Alt-Enter fragments will be really, really confusing.

  2. People expect feedback after execution. The complete absence of feedback after ;; or Alt-Enter is really confusing, it's like nothing else in F#.

  3. We've always made a mistake by not giving feedback after successful #r. But I think it becomes even more important after #r "nuget: ...

  4. I do recall the decision to bundle up multiple fragments but I didn't realise they extended over ;; or Alt-Enter. Did we really intentionally do that even combining over ;; ? Perhaps we've had some discussion on it?

  5. There is a tradeoff with regard to Alt-Enter (which sends a ;; implicitly: If people execute a bunch of related #r one by one then they may get different resolutions. But that happens elsewhere in F# interactive, so over time people learn to execute as a group.

Here's an example where the absence of feedback even after a successful #r is problematic:

  1. Execute this, no feedback:

    r "nuget:RestoreSources=https://ci.appveyor.com/nuget/diffsharp";;

  2. Execute this, no feedback:

    r "nuget: DiffSharp-reference,Version=0.9.5-preview-2006210200";;

  3. Execute this:

    1;;

    and we get feedback:

    [Loading C:\Users\dsyme\AppData\Local\Temp\nuget\13352--dfe928cd-07f4-42c7-91b0-b6148e8088ac\Project.fsproj.fsx] namespace FSI_0005.Project

    But the feedback given is about the auto-generated 13352--dfe928cd-07f4-42c7-91b0-b6148e8088ac\Project.fsproj.fsx but that's not meaningful to the user. It's not what we should be showing from a usability perspective.

Anyway I think we should go over this and spec out the interactions and feedback we expect and support for different incremental executions (both succeeding and failure) in Console and Script-Alt-Enter modes and see what we can sort out. At the moment it feels like we're not in the right place.

dsyme commented 4 years ago

Also I'd really like us to align the syntax for referencing between fsi.exe and .NET Interactive if possible. What do we need to change to do this? I'm finding it confusing switching between the different syntaxes.

jonsequitur commented 4 years ago

We've been experimenting with syntax at the .NET Interactive level before pushing it down to CSI and FSI, hence the current inconsistency.

An interesting difference is that magic commands in .NET Interactive (much like in IPython/Jupyter) are parsed as POSIX-like command lines. In that context this helps unify the behavior, and we get a good extensibility story via System.CommandLine, but it clashes a bit with the compiler directives.

But unburdened of history, a syntax like this would likely be cleaner and better support tooling such as completion and hover text:

#!nuget add-source https://donsyme.pkgs.visualstudio.com/TorchSharp/_packaging/packages2/nuget/v3/index.json
#!nuget DiffSharp -v 1.2.3
dsyme commented 4 years ago

Closing this as it's covered by https://github.com/dotnet/fsharp/pull/9652 and https://github.com/dotnet/fsharp/issues/9540