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

#langversion #814

Open
Happypig375 opened this issue Dec 3, 2019 · 12 comments
Open

#langversion #814

Happypig375 opened this issue Dec 3, 2019 · 12 comments

Comments

@Happypig375
Copy link
Contributor

@Happypig375 Happypig375 commented Dec 3, 2019

#langversion

I propose we add #langversion to F# scripts.

#langversion "preview"
let x = () in nameof x;; // :)

The existing way of approaching this problem in F# is creating an entire project just to make scripts with nameof usable.

Microsoft (R) F# Interactive version 10.6.0.0 for F# 4.7
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> let x = () in nameof x;; // :(

  let x = () in nameof x;; // :(
  --------------^^^^^^

stdin(1,15): error FS0039: The value or constructor 'nameof' is not defined.

> 

Pros and Cons

The advantages of making this adjustment to F# are

  1. Ability to use new F# features in script files
  2. More consistency with actual F#

The disadvantages of making this adjustment to F# are none that I can think of.

Extra information

Estimated cost (XS, S, M, L, XL, XXL): S

Related suggestions: None

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this
@baronfel

This comment has been minimized.

Copy link
Collaborator

@baronfel baronfel commented Dec 3, 2019

You can also run a script with preview features in an instance of FSI that's preview enabled: dotnet FSI --langversion:preview

Which is not to say that this shouldn't be done, just giving you a workaround.

@cartermp

This comment has been minimized.

Copy link
Member

@cartermp cartermp commented Dec 3, 2019

It's very easy to implement this as a new #r directive, but rationalizing this with an F# scripting environment is pretty wild. Consider this script, where you execute it line-by line:

#langversion "preview"
let x = 12
let name() = nameof x
#langversion "4.7"
printfn "%s" (name ())

What should happen? The name function is already defined, compiled, and evaluated. So we can't emit a compile error without some additional machinery in the compiler that traces arbitrary function calls to see if something is being used but it's not defined or unavailable.

This is also even more difficult in a Jupyter scripting environment, where you might have tens of cells, and you can reference things defined in any other cells (not just those defined above where you're working!). You can imagine the above script split into two arbitrary cells in a very large notebook - what happens to other cells if you set the LangVersion to a lower language version somewhere in the notebook?

Questions like this didn't yield any satisfying answers, hence it was not implemented.

@matthid

This comment has been minimized.

Copy link

@matthid matthid commented Dec 3, 2019

@cartermp Why is it even that complicated? Hash directives already indicate that it is something "static". Therefore in a regular script file the "last" one would win. In an interactive environment, you would just switch the compiler settings for new code as there is really nothing else you can do.

Isn't this already similar to when you use the current directory and change it via #cd or #silentcd? Consider code where you interactively use the FSI current directory or store it in a runtime variable. Yes we cannot change that variable later.

Alternatively, we can just make version downgrades fail or ignore them silently.

@cartermp

This comment has been minimized.

Copy link
Member

@cartermp cartermp commented Dec 4, 2019

It's complicated mostly because the notion of switching one's effectively language version interactively isn't what it was originally designed for. While you can certainly do this in a project file in tools like VS and have the editor react accordingly, this isn't interactive - it's akin to rebuilding again, just at design-time. So it's more like restarting an FSI session and reloading everything than an interactive switch in the current tooling.

The majority case is easy here; like almost all other #r directives it would only be top-level and functionally equivalent to have started the FSI session with --langversion:<VER>. But we didn't want to implement this half-cocked for the minority case. This is less of a problem in small scripts, but is much more difficult to track down in a large notebook, which is now a supported scenario for interactive F# programming.

Additionally, there's no good way to handle script IntelliSense for this. Currently, nameof gives a diagnostic in the editor if you're not using the preview language version. In the above code sample, would it still do that? Probably not, since it's valid for the first half of that script. But it would be invalid in the latter half if copy/pasted, so we'd probably want to make sure that works. An analogue here is #if defs in source, but we don't handle those nearly as well as the C#/VB editor today so I suspect there would be holes or simple lots of bugs today. Since we're planning on bringing a rich editing experience to Jupyter, it's also critical that getting this sort of thing right also work there, where the code that sets the language version may not be in the same cell you're working on.

@matthid

This comment has been minimized.

Copy link

@matthid matthid commented Dec 4, 2019

I see why intellisense might be a bit hard to do correctly. I don't get why Jupyter is so special - I guess I'm not familiar enough with their workflow - but in any case thanks for the details! So I assume in the end this feature is just not an 'S' but a lot of work and includes some risks and at this point it is debatable if it is even worth the effort.

@cartermp

This comment has been minimized.

Copy link
Member

@cartermp cartermp commented Dec 4, 2019

Yeah, to handle the majority case it's probably an S. So I wouldn't necessarily rule it out, but I'd expect a handful of bugs immediately from curious people who want to take it further.

@KevinRansom

This comment has been minimized.

Copy link

@KevinRansom KevinRansom commented Jan 7, 2020

As a rule, we want to provide tools that encourage developers to adopt the latest builds eagerly. This feature was designed to be in support of that goal.

The primary intent of the languageversion switch is to enable a developer who is working on a project using a stable version of F# to peg that project to that specific version of F#, and so not introducing dependencies on newer features of F# until the project team has declared an interest in completing the transition to the latest language features.

The secondary intent of the feature was to enable developers to kick the tyres on preview language features by explicitly selecting preview.

Scripting developers can use the command line switch to constrain their scripts to a down-level language version if they so choose. Although the global.json file is the preferable choice for that. Scripts that self-adapt to the ambient fsi language version is not a scenario that we currently target.

Kevin

@Happypig375

This comment has been minimized.

Copy link
Contributor Author

@Happypig375 Happypig375 commented Jan 7, 2020

So preview features like nameof cannot be used in the Visual Studio F# Interactive? It does not support --langversion, any suggestions will have to be done inside F# code.

@cartermp

This comment has been minimized.

Copy link
Member

@cartermp cartermp commented Jan 7, 2020

Currently we don't plan on enabling opt-in previews with the Visual Studio FSI, but we'd certainly accept a PR that implemented the option in tooling.

@abelbraaksma

This comment has been minimized.

Copy link

@abelbraaksma abelbraaksma commented Jan 7, 2020

@Happypig375, do you mean that the workaround suggestion by @baronfel doesn't work? #814 (comment)

@Happypig375

This comment has been minimized.

Copy link
Contributor Author

@Happypig375 Happypig375 commented Jan 7, 2020

It only works for independent FSI instances.

@KevinRansom

This comment has been minimized.

Copy link

@KevinRansom KevinRansom commented Jan 7, 2020

@Happypig375 we or someone else can probably add UI to enable preview in VS Fsi. That is a good proposal. I'm kind of sorry I hadn't thought of it already, however, we have only recently decided that we will preview F# 5.0 language features in the 4.7 compiler the previous plan was to restrict them to dotnet 5.0 previews.

I hope this alleviates your concerns

Kevin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants
You can’t perform that action at this time.