Juliaで何らかの計算を行いたい場合、インプットをファイルとして与えたいことがありますよね。
例えば、
L = 3
g = true
のような。テキストデータとしてこのインプットを保存して読み込むという手もありますし、その他のファイルフォーマットを使うこともあるでしょう。
今回は、
L = (3,2)
name = "dog"
namedict = Dict()
namedict["dt"] = 0.1
matrix = rand(Float64,2,2)
f(x) = 2x
beta = f(2.4)
をインプットファイルにして変数を読み込む方法について述べます。
これはJuliaのコードそのものですね。つまり、このようにインプットファイルで値を定義したり値を計算したりして、その結果をインプットファイルに入れる、という方法についてです。
インプットファイルに関数を入れられるので、
x = 3
y = x+4
z = cos(x)*exp(z)
みたいなインプットファイルが可能になります。
コード
以下のコードがそれを実現します。
module Loadfromfile
export loadfromfile
function loadfromfile(filename)
include(pwd()*"/"*filename)
return L,name,beta,namedict,matrix
end
end
非常に簡単なコードですね。このコードと
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で呼ばれたコードの変数のスコープはどうなっているのでしょうか?
以下のコードを実行してみましょう。
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)
の中でよびましたので、何か挙動が違うようです。
例えば、
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内でどこでも使えるグローバル変数)として定義されているということです。
この挙動を知らなかったため大分試行錯誤することになりました。
実用的な例
実用的な例としては、何が返ってくるかわかるように初期値を指定する
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
のが良いかもしれません。
これの利点は
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])
のようにインプットを定義できる点です。インプットでは辞書型の変数や行列の型を定義するのではなく、値を入れる形にしています。
これにより、インプットファイルを記入する側は変数の定義に気を取られずに済みます。