3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

F# ScriptでPythonの__name__を真似する

Last updated at Posted at 2016-12-19

最初に起動したスクリプトなのか、別のスクリプトから読み込まれたスクリプトなのか、実行時に判定する方法を調べました。

【2020.05.28】 F# Interactive に対応しました。

コマンドライン引数については以下の記事を参照してください。

F# スクリプトを手軽に扱うには VS Code + Ionide がお勧めです。

Python

Pythonでは以下のように記述することで、最初に起動されたのかimportされたのかを判断することができます。

test1.py
if __name__ == '__main__':
    print("main")
test2.py
import test1
実行結果
$ python test1.py
main

$ python test2.py

F# スクリプト

これをF# スクリプトで真似してみました。一時変数が残らないように do 内に記述します。

Test1.fsx
do
    let frames = System.Diagnostics.StackTrace().GetFrames()
                 |> Array.map (fun frame -> frame.GetMethod().Name)
    if frames.[0] <> "main@" || Array.contains "EvalParsedSourceFiles" frames then () else
    printfn "main"
Test2.fsx
#load "Test1.fsx"
実行結果
>fsi Test1.fsx
main

>fsi Test2.fsx

>fsc Test1.fsx
Microsoft (R) F# Compiler バージョン 10.6.0.0 for F# 4.7
Copyright (C) Microsoft Corporation. All rights reserved.

>fsc Test2.fsx
Microsoft (R) F# Compiler バージョン 10.6.0.0 for F# 4.7
Copyright (C) Microsoft Corporation. All rights reserved.

Test2.fsx(1,18): warning FS0988: プログラムのメイン モジュールが空です。実行しても何も処理されません

>Test1
main

>Test2

調査

このコードはスタックフレームの差分に基づいています。

Test3.fsx
for frame in System.Diagnostics.StackTrace().GetFrames() do
    printfn "%s" (frame.GetMethod().Name)
Test4.fsx
#load "Test3.fsx"
ログ採取
>fsi Test3.fsx > Test3.log
>fsi Test4.fsx > Test4.log
差分
--- Test3.log   2020-05-28 05:37:40.295828000 +0900
+++ Test4.log   2020-05-28 05:37:46.470496400 +0900
@@ -9,8 +9,8 @@
 iter
 Iterate
 ProcessInputs
-EvalParsedDefinitions
-EvalParsedExpression
+EvalParsedSourceFiles
+EvalSourceFiles
 Invoke
 InteractiveCatch
 ExecInteraction

EvalParsedDefinitions があれば最初の起動、EvalParsedSourceFiles があれば別のスクリプトから読み込まれていると判断できるようです。

旧バージョン

当初は次のようにしていました。Python の記述方法に似ていますが、F# Interactive に未対応です。

Test1.fsx
if System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name = "main@" then
    printfn "main"
Test2.fsx
#load "Test1.fsx"
実行結果
>fsi Test1.fsx
main

>fsi Test2.fsx
main

>fsc Test1.fsx
Microsoft (R) F# Compiler version 11.0.50727.1
Copyright (c) Microsoft Corporation. All Rights Reserved.

>fsc Test2.fsx
Microsoft (R) F# Compiler version 11.0.50727.1
Copyright (c) Microsoft Corporation. All Rights Reserved.

Test2.fsx(1,18): warning FS0988: Main module of program is empty: nothing will happen when it is run

>Test1
main

>Test2

参考

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?