裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

Julia の変数スコープ

2021年01月28日 | ブログラミング

わかりにくいかもしれないので,簡単な例を挙げておこう。

test99.jl という名前のファイルに以下の内容が入っているとする

for i = 1:10
    s = i == 1
    s = s + i
end
println(s)

コマンドラインで

$ julia test99.jl

とすると,

ERROR: LoadError: UndefVarError: s not defined
Stacktrace:
 [1] top-level scope at /Users/foo/Desktop/Julia/test99.jl:5
 [2] include(::Function, ::Module, ::String) at ./Base.jl:380
 [3] include(::Module, ::String) at ./Base.jl:368
 [4] exec_options(::Base.JLOptions) at ./client.jl:296
 [5] _start() at ./client.jl:506
in expression starting at /Users/foo/Desktop/Julia/test99.jl:5

となる。

REPL で,一番最初に

include("test99.jl")

を実行すると,同じエラーが出る(少し違うが)

LoadError: UndefVarError: s not defined
in expression starting at /Users/foo/Desktop/Julia/test99.jl:5

Stacktrace:
 [1] top-level scope at /Users/foo/Desktop/Julia/test99.jl:5
 [2] include(::String) at ./client.jl:457
 [3] top-level scope at In[2]:1
 [4] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091

この後例えば

s = 0

という行を実行させた後,再度

include("test99.jl")

を実行すると

0
┌ Warning: Assignment to `s` in soft scope is ambiguous because a global variable by the same name exists: `s` will be treated as a new local. Disambiguate by using `local s` to suppress this warning or `global s` to assign to the existing global variable.
└ @ nothing /Users/foo/Desktop/Julia/test99.jl:2

となる。

さて,普通のプログラミング言語だとどうなっていたっけ?と思い,まずは R でやってみる。

Julia でのプログラムを以下のように書き換えて test99.R に保存する。

for (i in 1:10) {
    s = i == 1
    s = s + i
}
print(s)

コマンドラインからこれを Rscript で実行すると

$ Rscript test99.R
[1] 10

なんのエラーもなく,期待される答え 10  を表示する。

R か RCommander で

source("test99.R")

としても,同じく 10 を表示する。エラーはない。

次に Python でやってみる。以下のプログラムを test99.py として保存する。

for i in range(1, 11):
    s = i == 1
    s = s + i
print(s)

コマンドラインからは

$ python3 test99.py
10

となるし,REPL でもエラーなく,同じ答え 10 が表示される。

 

我々としては,R や Python の振る舞いの方が普通に思われるが,確かに for ループの中で最初に s にアクセスするときは,「s なんかないよ」というのが理にかなっているのかも知れないなあ。

さて,悩んでいてもどうにもならないので,対策を考える。

for の内と外で s といっても違いがあるということで,

s = 999
for i = 1:10
    s = i == 1
    s = s + i
end
println(s)

としただけでは,まだ期待するような結果にはならない。

999
┌ Warning: Assignment to `s` in soft scope is ambiguous because a global variable by the same name exists: `s` will be treated as a new local. Disambiguate by using `local s` to suppress this warning or `global s` to assign to the existing global variable.
└ @ nothing /Users/aoki/Desktop/Julia/test99.jl:3

ところで,関数もまた変数スコープを持つので,このプログラムを関数定義でくるんでやる。

function func()
    s = 999
    for i = 1:10
        s = i == 1
        s = s + i
    end
    println(s)
end

これではじめて,for の内と外の s が同じものになる。その後で,関数を読んでやれば,期待する答え 10 が表示される。

s = 999初期化は不要だが定義が必要としたものだ。

func()
10

 

 

コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« Julia の変数スコープに注意 | トップ | MATLAB プログラムを Julia ... »
最新の画像もっと見る

コメントを投稿

ブログラミング」カテゴリの最新記事