JuliaでJuliaのコードをインプットとする

Juliaで何らかの計算を行いたい場合、インプットをファイルとして与えたいことがありますよね。
例えば、

```
L = 3
g = true
```
のような。テキストデータとしてこのインプットを保存して読み込むという手もありますし、その他のファイルフォーマットを使うこともあるでしょう。

今回は、

```julia:input.jl
L = (3,2)
name = "dog"
namedict = Dict()
namedict["dt"] = 0.1
matrix = rand(Float64,2,2)
f(x) = 2x
beta = f(2.4)
```
をインプットファイルにして変数を読み込む方法について述べます。
これはJuliaのコードそのものですね。つまり、このようにインプットファイルで値を定義したり値を計算したりして、その結果をインプットファイルに入れる、という方法についてです。
インプットファイルに関数を入れられるので、

```julia:testinput.jl
x = 3
y = x+4
z = cos(x)*exp(z)
```
みたいなインプットファイルが可能になります。

# コード
以下のコードがそれを実現します。

```julia
module Loadfromfile
    export loadfromfile

    function loadfromfile(filename)
        include(pwd()*"/"*filename)
        return L,name,beta,namedict,matrix
    end
end
```
非常に簡単なコードですね。このコードと

```julia:test.jl
module Testcode
    using ..Loadfromfile    
    function test(filename)
        variables = loadfromfile(filename)
        for v in variables
            display(v)
            println("\t")
        end
    end
end

using .Testcode
Testcode.test(ARGS[1])
```
を用いれば、

```
julia test.jl input.jl
```
を実行すると、

```
(3, 2)	
"dog"	
4.8	
Dict{Any,Any} with 1 entry:
  "dt" => 0.1	
2×2 Array{Float64,2}:
 0.426489   0.860886
 0.0233972  0.273282
```
となりますので、ちゃんと値を定義できていることがわかります。

# コードの説明
以下に説明を行います。

ポイントはinclude文です。
include文、元々はModuleを複数ファイルに分割したりする時に使います。ですので、Moduleのすぐ下にincludeを置くことが多いですよね。
このようにfunctionの中に置くことも可能です。
しかし、注意点があります。includeで呼ばれたコードの変数のスコープはどうなっているのでしょうか？
以下のコードを実行してみましょう。

```julia
module Loadfromfile
    export loadfromfile

    function loadfromfile(filename)
        include(pwd()*"/"*filename)
    end
end

module Testcode
    using ..Loadfromfile
    
    function test2(filename)
        loadfromfile(filename)
        println(Loadfromfile.beta)
    end
end

using .Testcode
Testcode.test2(ARGS[1])
```
これを実行すると、

```
4.8
```
と出力されます。```Loadfromfile.beta```の値が出ています。
しかし、include文は```function loadfromfile(filename)```の中でよびましたので、何か挙動が違うようです。
例えば、

```julia
module Loadfromfile
    export loadfromfile

    function loadfromfile(filename)
        beta = 100
    end
end

module Testcode
    using ..Loadfromfile
    
    function test2(filename)
        loadfromfile(filename)
        println(Loadfromfile.beta)
    end
end

using .Testcode
Testcode.test2(ARGS[1])
```
を実行すると、

```
ERROR: LoadError: UndefVarError: beta not defined
```
となります。これは当然です。betaは```function loadfromfile(filename)```の中で定義していますので、```module Loadfromfile```の中には定義されていません。
一方、includeを使った場合はbetaを呼び出すことができています。
つまり、module内のどこでinclude文を呼んだとしても、module内の最上位変数（module内でどこでも使えるグローバル変数)として定義されているということです。
この挙動を知らなかったため大分試行錯誤することになりました。

# 実用的な例

実用的な例としては、何が返ってくるかわかるように初期値を指定する

```julia
module Loadfromfile
    export loadfromfile

    L = (5,3)
    name = "test"
    beta = 0.8
    namedict = Dict()
    matrix = zeros(Float64,3,3)

    function loadfromfile(filename)
        include(pwd()*"/"*filename)
        return L,name,beta,namedict,matrix
    end
end
```

のが良いかもしれません。
これの利点は

```julia:input2.jl
L = (3,2)
name = "dog"
namedict["dt"] = 0.1
matrix[1,2] = 4
function coscossinsin(x,y)
    cos(x)*cos(y) + sin(x)*sin(y)
end
beta =  coscossinsin(matrix[1,2],L[2])
```
のようにインプットを定義できる点です。インプットでは辞書型の変数や行列の型を定義するのではなく、値を入れる形にしています。
これにより、インプットファイルを記入する側は変数の定義に気を取られずに済みます。