Julia のIDE Juno を使って快適な Julia との生活をする手引き(後半)

# 注意

- Juno のメンテナーが VSCode に乗り移る動きがあります．今後は VSCode を使っていくと良いと思います．

  - [JuliaCon 2020 | (Juno 1.0) VSCode for Julia 1.0 | Sebastian P., Shuhei K., David A.](https://youtu.be/rQ7D1lXt3GM)
  - [JuliaCon 2020 | Using VS Code for Julia development | David Anthoff](https://www.youtube.com/watch?v=IdhnP00Y1Ks&t=3s)

# 本日は

[Julia のIDE Juno を使って快適なJuliaとの生活をする手引き(前半）](https://qiita.com/SatoshiTerasaki/items/3dda33ece801b75e248c)
の続きです．前回はJulia,Atom,Junoの導入と最低限の動作の確認をしました．
ここでは可視化を行うパッケージを例に簡単な描画の結果の閲覧をする方法，デバッガを動かす方法をノベマス．

# 可視化しよう

## グラフの描画ここでは GR バックエンドの [Plots.jl](https://github.com/JuliaPlots/Plots.jl) を例にグラフを描画する例を見てみましょう．

Atom上でファイルに書いて実行してもいいですしREPLで実行するでも良いです．ここではAtomのREPLを立ち上げて実行をしています．そうすると描画の結果が`Plots`という領域に表示されます．これはエディタの左端に見えるヒストグラムのようなアイコンをクリックすることでも閲覧できます．

`plots([sin,cos],-pi,pi)` は `sin`, `cos` を指定した範囲で描画するというものです．人間は欲が出るものでこの色を赤にしたい，青にしたいとか色々思うところはあると思いますが，それはそれで大変なので公式ドキュメントを眺めてみてください．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/f97aa96d-80aa-aaa3-3056-dcd6b69d3f1a.png)

## 画像も表示

画像も見たいでしょう．

```julia:alt_imshow
using TestImages
using Plots

cameraman=testimage("cameraman");
lena=testimage("lena");
p1 = plot(cameraman);
p2 = plot(lena);
plot(p1, p2, layout = (1, 2), size = (600, 300))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/b36257c6-984c-77d6-e0aa-ef2de47305ed.png)

ここで，`plot` という関数がいっぱい出てきますが Julia の [multiple dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch) によって入力される型によって method が変わっています．とりあえず `plot` という関数の名前だけ覚えておいて描画したいオブジェクトを入れ込みたいものをポコポコ `plot` に突っ込ませればいいわけです．Julia における multiple dispatch のコンセプトについては公式ドキュメント [Methods](https://pkg.julialang.org/docs/julia/THl1k/1.1.1/manual/methods.html#Methods-1) の冒頭の段落にエッセンスが詰まっています．

### なぜ ImageView を使わないのか

画像処理のライブラリ Images.jl と関連して ImageView.jl というJuliaのパッケージがあります.
名前の通り画像を表示するものですが，これの依存となる Cairo.jl のビルドが各方面のOSでことごとく失敗するIssueが出てます．Macも例外ではありません．[一応回避策はある](https://github.com/JuliaGraphics/Cairo.jl/issues/271) みたいですが，私のiMacでは回避できませんでした．システムの brew と Juliaの Homebrew.jl が管理している brew の両方をマネージしてビルドを成功させないといけないのはちょっと辛いです．現時点では Plots.jlの `plot` を用いるか PyCall.jl 経由で慣れ親しんでいる Python の画像処理ライブラリを呼び出すという選択が良いでしょう．

## もう少し華やかな例

[Lorenz Attractor](https://docs.juliaplots.org/latest/) のコードをそのままREPLにペーストします．そうすると Plots のパネルにぐるぐると描画される様子が見られます．必要に応じて `brew install ffmpeg` などでgifを作るためのパッケージが必要になります．

# あぁ何もわからん

```julia
using TestImages
using Plots

cameraman = testimage("cameraman");
lena = testimage("lena");
p1 = plot(cameraman);
p2 = plot(lena);
plot(p1, p2, layout = (1, 2), size = (600, 300))
```

今回は簡単で名前から `testimage` は `TestImages.jl` で定義されている関数だろうというのは想像つきます. `using TestImages` することで スコープに `testimages` なる識別子が導入されます．Juliaはどこに何があるかは知っている，知っていないのはお前だけな状態から救うのにJunoの力を借りましょう．

# Help mode で Julia に救いの手を求める

公式のドキュメントにもあるように

- https://docs.julialang.org/en/v1/stdlib/REPL/#Help-mode-1

Help mode を使います．ちゃんとした？ライブラリであれば docstring が書いてあるのでそれを手掛かりに調べるのも良いでしょう．

```julia
julia> #?キーを入力
help?> #切り替わる
help?> testimage
search: testimage TestImages

  testimage(filename, [ops...])

  load test image that partially matches filename, the first match is used if there're more than one. If
  ops is specified, it will be passed to load function. use TestImages.remotefiles to get a full list of
  available images.

  Example
  ≡≡≡≡≡≡≡≡≡

  julia> using TestImages
  julia> testimage("cameraman.tif")
  julia> testimage("cameraman")
  julia> testimage("c")
julia> # この方法でも良い
julia> @doc testimage
```

# `@which` マクロを用いる

 手掛かりを知るという意味では `@which` マクロを使う方法もありますね．

```
help?> @which
  @which

  Applied to a function or macro call, it evaluates the arguments to the specified call, and returns the
  Method object for the method that would be called for those arguments. Applied to a variable, it returns
  the module in which the variable was bound. It calls out to the which function.

julia> @which testimage
TestImages
```

- https://juliadocs.github.io/Julia-Cheat-Sheet/ も見ると良いでしょう．

# Juno「え，私を使ってよ・・・」

JunoのDocumentationを検索する機能を使ってみましょう．○の中に i があるアイコンをクリックしてそこに `testimages` とか `plot` などを入れてみましょう．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/1c2ab814-ff79-4929-6ff8-471a6c058e10.png)

ラムダは関数を，ダンボールはパッケージを表しているみたいですね．`testimage` をクリックすると対応するソースコードにジャンプします（下図参照）．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/e1326361-3202-d46e-9041-76095ce363fe.png)

何かみたことがある文字が出ていますが，Help mode での出力結果は関数に紐づいている docstring だったことがわかります．

[See Documentation](https://docs.julialang.org/en/v1/manual/documentation/#Documentation-1)

# マウス「右クリック．．．」

`plot` はどうでしょう？ multiple dispatch で同じ名前でも機能が違うと戸惑う人もいるのではないでしょうか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/071eaebb-04ed-e066-f285-5deaad9b3fa2.png)

とりあえず，調べたい対象に右クリックをして `Julia-Client -> Go to Definition` することで所望の結果にアクセスする手掛かりを見つけることができます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/6e903f0c-d365-49b6-fae4-57127aafa1b8.png)

うーんどれかわからんけれど，型を合わせるならコレかな？という雰囲気で探すことはできますね．

# 走らせて確認したい．そんなあなたにデバッガ

```julia
plot(p1, p2, layout = (1, 2), size = (600, 300))
```

の行にブレークポイントを設定しましょう．ブレークポイントは行番号の隣をクリックすることで設定できます．赤いポチが見えれば成功です．外すときはそのポチを押せば元に戻ります．

REPL で次を実行します．

```julia
Juno.@enter plot(p1, p2, layout = (1, 2), size = (600, 300))
```

Junoの便利なところはソースで実行してもその名前がREPLでも使えるということです．（裏目にもなりますが）

このようにすると指定した式の評価とデバッガが起動し，虫マークのアイコンの領域が出現します．（下の図参照）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/d2e477e3-471c-f89a-932d-e2a5e5416374.png)

結論としては

```julia
function plot(plt1::Plot, plts_tail::Plot...; kw...)
    plotattributes = KW(kw)
    preprocessArgs!(plotattributes)
```

が呼び出されたことになります．自分で書いたソース以外の部分に深掘りして探ることができます．

ちなみに `...` がいっぱい出てきますが，splat operator というようです．実は Help mode で教えてくれる．

```
help?> ...
search:

  ...

  The "splat" operator, ..., represents a sequence of arguments. ...
  can be used in function definitions, to indicate that the function
  accepts an arbitrary number of arguments. ... can also be used to
  apply a function to a sequence of arguments.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> add(xs...) = reduce(+, xs)
  add (generic function with 1 method)
  
  julia> add(1, 2, 3, 4, 5)
  15
  
  julia> add([1, 2, 3]...)
  6
  
  julia> add(7, 1:100..., 1000:1100...)
  111107
```

お気持ち程度で Python の list などのデータ構造の前につける `*` な存在だと思ってください（実際の挙動は違いますが）

# 条件を指定してブレークする

例えば下記のようなループが入る関数の中を見たいとします．ブレークポイントを置いておくとループが回るたびにブレークします．ループが一定回数などの特定の条件でブレークすることができれば便利ですよね？

```julia
function main()
    for i in 1:10
        j = i - 1
        k = i + 1
        @show i^2 + j^2 + k^2
    end
end
```

そこで Debugger のパネルの中にある Breakpoints　を見てみましょう．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/d627a49a-f784-7f7b-4e57-193667e64763.png)

上の画像の右下にあるYの字のアイコンを押します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/06fa945d-bf75-bb6a-3c41-cad6eb8d4943.png)

Condition の条件を記述して Confirm ボタンを押します．ブレークポイントは青色に変色します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/fc9ed1dc-1cb1-f307-5cf3-6a517dd3cc33.png)

デバッガのDebug continue という早送りボタンを押すと確かに `k` が６を満たす時にブレークする様子がわかります．ループが１００以上の時に不具合が起きる・・・みたいな時に調べることができるのは便利ですね．

# おまけ

自分でUI位置を変更したい．

julia-client の中の設定で選ぶことができます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/0bc4a103-3e3b-b7b3-8bcc-b9f201cffd70.png)

以上で後半戦終了ですお疲れ様でした．

# まとめ

前半ではJunoの導入と簡単な動かし方を示しました．
後半戦ではより実践的に可視化パッケージを使って結果をAtom内のUIに埋め込むことをしました．
ソースコードを読む時にJuliaのドキュメントを見る方法，Go to definition の方法を学びました．
さらに深く進む時にデバッガを使うと実行時のデータの処理がどのようにして行われるかを知ることができました．