fslang-suggestions icon indicating copy to clipboard operation
fslang-suggestions copied to clipboard

Detect the 'entry' script in F# scripts

Open onionhammer opened this issue 7 years ago • 17 comments

I propose we add syntax to detect whether the current F# script is being run as the entry-point

#if __MAIN__
 .. Main code here
#endif

In Python it is quite easy - and very very common to include code like this

if __name__ == "__main__":
  ...

The reason it exists is to facilitate composability; being able to reuse functions of a script in other scripts without actually executing the segment underneath "main".

There is no way to do this presently when running an FSI script (correct me if I'm wrong)

Pros and Cons

The advantages of making this adjustment to F# are that it would allow improved re-use of F# scripts by #loading them into other scripts

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • [x] This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • [x] I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • [x] 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:

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

onionhammer avatar Apr 10 '18 13:04 onionhammer

https://github.com/fsharp/fsharp/issues/825 for the discussion already had around this. This can already be done. I'm almost certain this is a byproduct of inadequate documentation around running scripts vs loading scripts. I don't think the author for example understands that you can have main in a script. I would greatly appreciate it if someone who knows more than I do help guide this user to understanding. I am certain this can be done as I have done it before but I was having trouble explaining it to this user.

voronoipotato avatar Apr 10 '18 14:04 voronoipotato

@voronoipotato when running in interactive, the test should come out 'true'; the "solution" provided in 825 is not adequate since running text will fail while running as a file would not.

Also there are discrepancies in the path; for example if I run "fsi myscript.fsx" the args will look different than "fsi ./myscript.fsx"

onionhammer avatar Apr 10 '18 14:04 onionhammer

If you load a script it will not run main. When you run a script it will.

voronoipotato avatar Apr 10 '18 15:04 voronoipotato

@voronoipotato By "run" do you mean compile and run?

jwosty avatar Apr 10 '18 15:04 jwosty

no I mean fsi script_name, am I wrong here?

voronoipotato avatar Apr 10 '18 15:04 voronoipotato

I guess if it doesn't invoke automatically you can just have code in the script after main, invoke main. This as I understand it doesn't get called after you load. I need to actually test this, but needless to say I have gotten this exact process working in the past with little fanfare.

voronoipotato avatar Apr 10 '18 15:04 voronoipotato

That wont let you run the script interactively @voronoipotato. If I highlight my script, right click "Run in Interactive" in VS or VS Code, the commandlineargs will not contain the name of the script in the path, whereas if I run python interactively "name" is automatically set to "main"

test.fsx

open System

if fsi.CommandLineArgs = [| __SOURCE_FILE__ |] then
    printfn "Main!"

powershell

PS C:\Development\Test> fsi .\test.fsx
PS C:\Development\Test> fsi test.fsx
Main!
PS C:\Development\Test> fsi Test.fsx
Main!
PS C:\Development\Test> fsi TEST.fsx
Main!
PS C:\Development\Test> fsi .\test.fsx one
PS C:\Development\Test> fsi .\test.fsx two
PS C:\Development\Test>

onionhammer avatar Apr 10 '18 15:04 onionhammer

That wasn't my answer @onionhammer

voronoipotato avatar Apr 10 '18 15:04 voronoipotato

Can we get some example scripts for the proposed solution, instead of talking hypotheticals, and see whether or not the language suggestion is moot? (I personally am not able to get fsharpi xyz.fsx to do anything correctly)

jwosty avatar Apr 10 '18 15:04 jwosty

@jwosty Do you mean you want to see sample use-cases or ?

onionhammer avatar Apr 10 '18 15:04 onionhammer

https://github.com/Microsoft/visualfsharp/issues/539

I think I was wrong. I tried to write a test case but as the issue states it doesn't respect [<EntryPoint>] .

voronoipotato avatar Apr 10 '18 17:04 voronoipotato

I wish for that functionality too. It would be great to be able to exclude some code from evaluation if it is not running as the main script file. I use if __name__ == "__main__": a lot in python and id makes my scripts very modular.

goswinr avatar Apr 16 '18 06:04 goswinr

Haven't found a better solution yet; feedback is appreciated as I'm new to the language:

open System.IO

let (+/) (path: string) (other: string) : string = Path.Combine(path, other)

let entry (path: string) : bool =
    Path.GetFullPath path = __SOURCE_DIRECTORY__ +/ __SOURCE_FILE__

if entry (Array.head fsi.CommandLineArgs) then
    printfn "Not really `__name__ == '__main__'`, but it works somehow."

mataha avatar Jul 03 '22 18:07 mataha