Julia 1.0の注意点

# 背景
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さんが[書かれていますが](https://qiita.com/bicycle1885/items/9f9297d34d5f2ad56358)、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公式のフォーラム](https://discourse.julialang.org/)が[阿鼻叫喚状態](https://discourse.julialang.org/t/list-of-working-packages-on-v-1-0/13779)になっていたのですが、１か月たって、主要なパッケージはほぼv1.0対応してきているので、普通に使う分にはv1.0で大丈夫になってきています。
v1.0では新しい[Packageマネージャー](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html)が導入されて、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`する
- 線形代数関係の関数など（`inv`や`det`、`Diagonal`、`Symmetric`、`eigvals`）を使うには、`using LinearAlegebra`
- 日付関連の関数(`now`や`Date`など）を使うには、`using Date`

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

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

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

```jlcon
julia> a = 0
       for i in 1:10
         a += i
       end
ERROR: UndefVarError: a not defined
```
となります。
正しくは、

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

とする必要があります。


Julia v1.0の変数スコープについての説明が[ここ](https://docs.julialang.org/en/v1/manual/variables-and-scoping/)にありますが、かいつまんで言うと

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

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

別の解決策としては、

```jlcon
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](https://github.com/JuliaLang/julia/issues/28789)があがっているので、おそらく、近いうち（Julia v1.1？）には、REPL上で実行するときだけは特別扱いされて、`global`が必要なくなると思われます。
ちなみに、[Jupyter](http://jupyter.org/)上ではJuliaを実行する場合には、すでに、[特別扱い](https://github.com/JuliaLang/IJulia.jl#opting-out-of-soft-scope)がされているので、`global`をつけなくても動きます。