44
25

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 5 years have passed since last update.

Julia 1.0の注意点

Last updated at Posted at 2018-09-14

背景

Julia v1.0 が2018/8/8にリリースされました。
Julia v1.0は、前バージョンであるv0.6からいくつかの変更点があるのですが、
今のところ世の中にある(とくに日本語の)Julia関連のドキュメントはv0.6以前のものが多いため、v1.0で実行しても動かないことがあります。
そこで、Julia v1.0を使うための注意点など、気づいた点を書いてみたいと思います。
実際には、とくにユーザーとして普通に使うだけならv0.6とv1.0の違いは大したことはないので、たいてい、ほんのちょっと変えれば動くのですが、その「ほんのちょっと」が分からないせいでJulianが減ってしまうのは悲しいので。

Julia v0.7のすすめ

すでに、@bicycle1885さんが書かれていますが、Julia v0.7から非推奨(deprecated)の警告メッセージを削除したものがv1.0になります。したがって、機能的には、ほぼ v0.7≒v1.0と考えてよいです。
上で書いたように、Julia v0.7(≒v1.0)は、前バージョンであるv0.6からいくつかの変更点があるわけですが、Julia v0.7では古い(v0.6時代の)書き方でコードを書くと、「この書き方は非推奨(deprecated)になりました。代わりにこう書いて下さい」という警告メッセージを出します。警告メッセージにしたがって新しい書き方に直せばよいわけです。
それに対して、v1.0では、古い書き方をすると、どう直せばいいのかという警告メッセージを出すことなく、単にエラーになってしまいます。

というわけで、とくにv0.6 時代のドキュメントを参考にしてJuliaのコードを書こうという方は、v1.0よりもv0.7を使うほうがよいかもしれません。

Packageのインストール方法

Julia v1.0が出たばかりの頃は、主要なPackageがv1.0では軒並み動作しないということで、Julia公式のフォーラム阿鼻叫喚状態になっていたのですが、1か月たって、主要なパッケージはほぼv1.0対応してきているので、普通に使う分にはv1.0で大丈夫になってきています。
v1.0では新しいPackageマネージャーが導入されて、Packageのインストールが劇的に速くなりました。Packageのインストールは、REPL上で]を押して、Pkgモードに入ってadd Package名とします。

ちなみに、v0.6時代には、Pkg.add("Package名")としていたわけですが、v1.0でやるとERROR: UndefVarError: Pkg not definedとエラーになってしまいます。これは、下に書きますが、多くの標準ライブラリがBaseの外に出されたのにともなってPkgも外出しされたためでして、最初に、Using Pkgとしておけば、Pkg.add("Package名")も動作します。

多くの標準ライブラリが明示的にusingが必要になった

v1.0では、多くの標準ライブラリが、Baseから外に出されました。BaseというのはJuliaを起動したときに自動的に読み込まれるパッケージなわけですが、ここから外に出された標準ライブラリを使うには、using ライブラリ名と明示的に記述する必要があります。

例えば、

  • @printfを使うには using Printfする
  • 線形代数関係の関数など(invdetDiagonalSymmetriceigvals)を使うには、using LinearAlegebra
  • 日付関連の関数(nowDateなど)を使うには、using Date

など、といった具合です。
標準ライブラリの一覧は、公式ドキュメントのStandard Libraryの項にあります。
とにかく、v0.6時代のコードを、v1.0動かしてERROR: UndefVarErrorと怒られたら、using 〇〇が必要な可能性が非常に高いです。(Julia v0.7を使っていれば「この機能を使うには、using 〇〇をしてね」という警告メッセージがでます。)

Scopeルールの変更

v0.6 → v1.0の変更点のうちでハマる可能性が高い罠に、変数スコープの変更があります。この変更はそれ自体は理にかなったものなのですが、REPL(普通にJuliaを起動してJulia>というプロンプトがでている画面)で、インタラクティブにJuliaを使う場合には注意が必要です。

たとえば、REPL上で、1から10までの数字の和を計算しようとして、Forループを使うと

julia> a = 0
       for i in 1:10
         a += i
       end
ERROR: UndefVarError: a not defined

となります。
正しくは、

julia> a = 0
       for i in 1:10
         global a += i
       end
julia> a
55

とする必要があります。

Julia v1.0の変数スコープについての説明がここにありますが、かいつまんで言うと

  1. Juliaには、グローバルスコープとローカルスコープの2種類のスコープがある
  2. for、while、let、関数定義などは新しいローカルスコープを導入する
  3. ローカルスコープはいくらでもネストできる。
  4. ネストされた内側のローカルスコープの中で、外側のローカルスコープで定義された変数を読み書きできる。
  5. ローカルスコープの中では、グローバルスコープで定義された変数を読むことはできるが、(デフォルトでは)書き変えることはできない
  6. ローカルスコープの中で、グローバルスコープの変数を書き換えたい場合には、global 変数名とグローバルスコープの変数を参照するということを明示的に記述する必要がある。

となります。とくに注意が必要なのはルール5でして、REPLでの実行は、つまりグローバルスコープでの実行なので、グローバルスコープで定義された変数aを、for文で導入されたローカルスコープ内で書き換えることができないためにエラーになったわけです。
正しく動作させるには、ルール6にしたがってglobal a += 1と変数aがグローバルスコープで定義された変数であることを明示する必要があります。

別の解決策としては、

julia> let
         a = 0
         for i in 1:10
           a += i
         end
         a
       end
55

のように、ルール3,4にしたがって、letでローカルスコープを導入して、その中でforを使うでもよいです。ネストされたローカルスコープの内側から、外側のローカルスコープ(letで導入されたローカルスコープ)で定義された変数aを読み書きできます。関数定義でもローカルスコープが導入されるので、letで囲む代わりに処理を関数にしてしまうでもよいです。Juliaでは、グローバルスコープで計算しないで可能な限り関数にするというのが鉄則なので(関数化しないとJuliaの強力な最適化機構が効きません)、関数化するほうが真っ当な解決策でしょう。

この新しい変数スコープの仕様は、とくにREPL上では非常に使いにくいということで、issueがあがっているので、おそらく、近いうち(Julia v1.1?)には、REPL上で実行するときだけは特別扱いされて、globalが必要なくなると思われます。
ちなみに、Jupyter上ではJuliaを実行する場合には、すでに、特別扱いがされているので、globalをつけなくても動きます。

44
25
1

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
44
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?