Juliaの開発環境構築

# はじめに
JuliaはMITで開発された言語で、2009年に誕生し、2012年に公表されました。開発者は[ブログ](https://julialang.org/blog/2012/02/why-we-created-julia/)（[訳はこちらから引用](https://project.nikkeibp.co.jp/idg/atcl/19/00016/071900001/?ST=idg-cm-software&P=1)）で

>我々は、オープンソースでリベラルなライセンスの言語がほしい。C言語の速度と、Rubyのダイナミズムがほしい。同図像性があり、LISPのような真のマクロを備えつつ、Matlabのように分かりやすくなじみのある数学的記法を使える言語がほしい。汎用的なプログラミングはPython並みに便利で、統計の扱いはR言語並みに容易で、文字列処理はPerl並みに自然で、線形代数はMatlab並みに強力で、プログラムの連結はシェル並みに得意な言語がほしい。習得が超簡単でありながら、筋金入りのハッカーが喜んで使い続ける言語がほしい。インタラクティブでありつつ、コンパイル方式の言語がほしい

と言っています。**最高にクール**ですよね。

そんなJuliaは日本語の書籍や記事がPythonに比べると非常に少ない・・のですが、つい先日[「1から始めるJuliaプログラミング」](https://www.coronasha.co.jp/np/isbn/9784339029055/)という書籍が出ました！
やはり書籍にまとまっている、というのは大変助かります。

本記事ではそんなJuliaのWindowsでの開発環境構築について書きます。

# Juliaのインストール
Juliaの[公式サイト](https://julialang.org/downloads/)からインストーラーをダウンロードしてインストールしてください。

## 環境変数の設定
- インストールしたJuliaのbinへのパスを **JULIA_HOME** などとして、Pathに **%JULIA_HOME%** を追加します。
- パッケージを開発する際、デフォルトでは ~/.julia/dev に作成されます。パスを変えたい場合は **JULIA_PKG_DEVDIR** を設定します。

# Jupyter Lab
実行時のコードや実行結果を残しながら開発していくのに、Jupyterは非常に便利です。そんなJupyter公式の[「I Python, You R, We Julia」](https://blog.jupyter.org/i-python-you-r-we-julia-baf064ca1fb6)という記事には

> The name is also a play on the languages Julia, Python, and R

とあり、JuliaはJupyterの名前の由来にもなっています。是非入れておきたいところ。

[Anaconda](https://www.anaconda.com/distribution/#download-section)などでインストールできます。Anaconda Promptで

```
(base) C:\Users\(ユーザー名)> jupyter lab
```

で立ち上げます。

なんということでしょう・・・名前の由来にもなっているというのに、**デフォルトではJuliaは入っていません**。

## Jupyter LabにJuliaを追加する
コマンドプロンプトかAnacondaプロンプトで、 julia と打つとJuliaのREPL（read-eval-print-loop）が立ち上がります。  

```julia
(base) C:\Users\(ユーザー名)> julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.4.0 (2020-03-21)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia>
```

REPLには5つのモードがあります。

- **Juliaモード**
  - Juliaのコードを実行するデフォルトのモード
- **パッケージモード**
  - **]** キーで起動
  - パッケージのインストールや依存関係を管理するモード
- **ヘルプモード**
  - **?** キーで起動
  - 関数やマクロのドキュメントを確認できます。
- **シェルモード**
  - **;** キーで起動
  - シェルのコマンドを実行するモード
- **サーチモード**
  - **Ctrl+r** で起動
  - コマンドの履歴を検索できます。

**]** キーを押してパッケージモードに入りましょう。パッケージモードで

```julia
(@v1.4) pkg> add IJulia
```

でIJuliaがインストールされます。再度Jupyter Labを立ち上げると、Juliaが使えるようになっているかと思います。

# PkgTemplatesとReviseをインストールする
## PkgTemplates
PkgTemplatesはパッケージの雛形を作ってくれます。 **]** キーを押してパッケージモードに入り

```julia
(@v1.4) pkg> add PkgTemplates
```

でインストールされます。BackspaceでJuliaモードに戻り、

```julia
julia> using PkgTemplates

julia> t = Template(user="(ユーザー名)")
```

などとすると、パッケージの雛形が作成されます。試しに Example というパッケージを作成してみましょう。

```julia
julia> t("Example")
```

JULIA_PKG_DEVDIR に設定したパス（設定していない場合は ~/.julia/dev）にExampleフォルダができます。
Exampleフォルダにはパッケージに必要なファイルが一通り作られます。

- .git/
- src/Example.jl
- test/runtests.jl
- LICENCE
- Manifest.toml
- Project.toml
- README.md

Project.toml や Manifest.toml にはそのパッケージの情報や、依存するパッケージが記載されます。**Manifest.tomlは直接編集する必要はありません**。開発パッケージへの依存パッケージの追加方法は後述します。

```julia
(@v1.4) pkg> status
```

とすると、その環境にインストールされているパッケージの一覧を確認できます。Example v0.1.0 が追加されていることを確認しましょう。

## Revise
パッケージの開発中はソースコードの修正は頻繁に行うことになりますが、デフォルトのJuliaでは一度usingしたパッケージはその時点で確定してしまいます。ソースコードを変更後、再度usingしても反映されません（プリコンパイルが走らない）。毎回REPLやJupyterを再起動しないとソースコードの修正が反映されない・・となると辛すぎますよね。

Reviseパッケージを用いるとソースコードを変更後、再度のusingも不要で修正が反映されます！  
パッケージモードで

```julia
(@v1.4) pkg> add Revise
```

して、~/.julia/config に下記二つのファイルを作成します。（[Using Revise by default](https://timholy.github.io/Revise.jl/stable/config/#Using-Revise-by-default-1)）

### startup.jl

```julia
atreplinit() do repl  
   try  
       @eval using Revise  
       @async Revise.wait_steal_repl_backend()  
   catch e  
       @warn(e.msg)  
   end  
end
```

### startup_ijulia.jl

```julia
try
    @eval using Revise
catch e
    @warn(e.msg)
end
```

これでREPLやJupyterを立ち上げるとデフォルトでReviseが利く状態になります。

### Reviseを用いない場合
Reviseを用いていない場合の挙動を見ていきます。先ほど作成した src/Example.jl を開いてみます。

```julia
module Example

greet() = print("Hello World!")

end # module
```

となっているかと思います。REPLやJupyterで

```julia
julia> using Example

julia> Example.greet()
Hello World!
```

となります。Example.jl を

```julia
module Example

greet() = print("Hello Julia!")

end # module
```

と変えてみます。再度REPLで実行しても

```julia
julia> Example.greet()
Hello World!
```

変わりません・・

### Reviseを用いた場合
Reviseを用いた場合、二度目の実行は

```julia
julia> Example.greet()
Hello Julia!
```

となり、修正が反映されています！

### 開発パッケージへの依存パッケージの追加
ExampleパッケージにLinearAlgebraパッケージを追加する例です。 **]** でパッケージモードに入り

  ```julia
 (@v1.4) pkg> activate Example
 Activating environment at `%JULIA_PKG_DEVDIR%\Example\Project.toml`

(Example) pkg> add LinearAlgebra

(Example) pkg> activate
Activating environment at `%USER_HOME%\.julia\environments\v1.5\Project.toml`

 (@v1.4) pkg> up Example
 ```

で追加されます。他の**開発**パッケージへの依存を追加する場合は **add ではなく dev** を用います。

```julia
(Example) pkg> dev Example2
```

# JuliaのIDE
## VSCode
この記事を書いた当時はJuliaのIDEとしてAtom + Junoを紹介していたのですが、今は**圧倒的にVSCodeをオススメ**します。

- REPLの動作がVSCodeの方が速い。ターミナルウィンドウはCtrl+Jで表示の切り替え。
- Julia FormatterのExtensionがある。コードが保存された状態でAlt+Shift+Fで適用。
- Git Graphが素晴らしい。
- LaTexの開発環境としてもVSCodeの方が快適。

## Atom + Juno
[Atom](https://atom.io/)はGitHubが開発したオープンソースのテキストエディタです。様々なパッケージを追加して機能を拡張できます。話が逸れますがLaTeXやる人は[texlive](http://www.tug.org/texlive/acquire-iso.html)とAtomと以下のパッケージを入れると環境が整うかと思います。実装したい数式をLaTeXで整理しておいてプレビューの数式を確認しながら実装する、実装しながら気付いたLaTeXの資料の誤りを修正する、というサイクルがやりやすいです。

- **メニューの日本語化**
  - japanese-menu
- **LaTeX用パッケージ**
  - latex
  - language-latex
  - latexer
  - pdf-view

(texliveを入れるときはISOイメージから入れた方が良いですね。。ハマりました。)

AtomをJuliaのIDEに拡張するJunoの画面はこんな感じです。

![Atom Juno.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235273/2b51ec24-0b8e-bf50-d87f-893783e08bf9.png)

レイアウトは自由ですが、この例では

- 左上にソースコード
- 左下にREPL
- 右上にWorkspaceとPlot Pane
- 右下にDebugger

を表示してみています。AtomにJunoを導入するには **uber-juno** パッケージをインストールします。

- ソースコードのあるコードにプロンプトがある状態で **Shift+Enter でそのコードを実行**
- 各変数が保持している値を確認できる**Workspace**
- グラフを描画する**Plot Pane**
- ブレークポイントやステップ実行が可能な**Debugger**
- REPLを裏にもう一つ起動しておいてくれるので、REPLを閉じて（Stop Julia [Ctrl+J, Ctrl+K]）**新たに開くときに待ちが短い。**

などJuliaの開発をサポートしてくれます。

### Debuggerの使い方
Example.jl を次のように編集してみます。

```julia
module Example

function example(len, n)
    xs = []

    for i in 1:n
        push!(xs, randn(len))
    end

    return xs
end

end # module
```

長さlenの正規乱数ベクトルをn本持つリストを返す、という関数です。この example() にブレークポイントを設定して、JunoのDebuggerを起動するには次のようにします。

```julia
(@v1.4) pkg> add Debugger  # Debuggerをインストール。初回のみ。

julia> using Debugger

julia> using Example

julia> breakpoint(Example.example)  #ブレークポイントの設定

julia> Juno.@run Example.example(5, 10)  # Debuggerの起動
```

Debugger Paneで「Debug: Next Line (Shift+F10)」で一行ずつ実行しながら、Workspace Paneで各変数の値を確認することができます。先ほど載せたJunoの画面が、この例でDebuggerを実行しているときのものになります。

**ブレークポイントは行番号の左側をクリックすることでも設定できます**。デバッグの途中で、ブレークポイントを追加で設定／解除もできます。ブレークポイントが設定されると行番号の左側に赤ポチが現れます。

# テスト
テストは test/runtests.jl に書きます。 Example/test/runtests.jl を次のように編集してみます。

```julia
using Example
using Test

@testset "Example.jl" begin
    len = 5
    n = 10

    xs = Example.example(len, n)

    @test length(xs) == n

    for x in xs
        @test length(x) == len
    end
end
```

example関数が指定したn本のベクトルを返してくるか、各ベクトルの長さはlenになっているか、を確認しています。
テストはパッケージモードで test [パッケージ名] で実行できます。

```julia
(@v1.4) pkg> test Example
    Testing Example
Status `C:\Users\(ユーザー名)\AppData\Local\Temp\jl_BpDq2B\Manifest.toml`
  [341bb147] Example v0.1.0 [`%JULIA_PKG_DEVDIR%\Example`]
  [2a0f44e3] Base64
  [8ba89e20] Distributed
  [b77e0a4c] InteractiveUtils
  [56ddb016] Logging
  [d6f4376e] Markdown
  [9a3f8284] Random
  [9e88b42a] Serialization
  [6462fe0b] Sockets
  [8dfed614] Test
Test Summary: | Pass  Total
Example.jl    |   11     11
    Testing Example tests passed
```

以上です。