python3
Jupyter
Nim

Jupyter notebookでNimを使い,グラフの可視化まで

本日は

あまり需要がないかもしれませんが, 
Nim をJupyter notebook で使えるようにしましょう.
そのために, INim を使います.

image.png

環境

  • Macbook12 inch
  • Nim 0.18.0
  • Python:3.5.5
    • matplotlib がインストールされているものとする.

install

動作に必要な ZeroMQ を導入します.

$ brew install zmq

INim を導入します.

$ git clone https://github.com/stisa/Inim
$ cd Inim
$ nimble install

動作

特にPythonとかと変わらないです.下記のようにコマンドを入力して
カーネルをNimに置き換えるだけです.

$ jupyter notebook

image.png

あとはPythonっぽくNimコードを書くことができます.

グラフの可視化

  • 通常(?)の単に文法の練習のためであれば上記の設定までで十分です. 冒頭の画像のようにグラフを描画するには色々と手間がかかります. というのは内部で Python の matplotlib をNimから呼び出すことをするためです.
  • Python の呼び出しは依存ライブラリの python3 を用いています.

以下 pyhton3 と書いたときはこのNimのライブラリを指すことにします.

python3の予備知識

どうやらpython3ではPythonをstaticかdynamic でバインディングする方法があるらしいです.ざっくりいうと Nim のコンパイル時に Pythonのヘッダーファイルとライブラリを指定してビルドする方法かとりあえずビルドしておいて, 実行時にPythonの共有ライブラリを参照する方法が取れるみたいです. ここではうまく動作した dynamic の方法を採用します.

手順1 libpython3.5m.dylib のコピー

かっこ悪いですが, libpython3.5m.dylib を実行するノートブックと同階層にコピーします. 多分パスを通しておけば良いと思います.

これは私の pyenv での環境では .pyenv/versions/miniconda3-3.19.0/lib にあります. 

手順2 リネーム 

python3 が認識できるように コピーしてきたlibpython3.5m.dylib を libpython3.5.dylib とリネームします.(mを消すだけ)

手順3 Jupyter notebook のセルにコードを書く

次のようにセルにてコードを書きます.

#>inlineplot 320 240
#>flags -d:py3_version=3.5 -d:py3_dynamic

show:  
    plot(@[0.0,0.5,1],@[0.0,1,2],"b","--","o","dots")
    xlabel("dotssss")
    legend()
    plot(@[0.0,0.2,0.8],@[0.0,1,2],"r","-","o","dotsline")

ここで #> はNimのカーネルのマジックコマンド のようです. #>inlineplot 320 240 で Pythonで言う所の%matplotlib inline 的な役割を果たすようです.
内部では import inim/pyplot をしているようですね.

https://github.com/stisa/INim/blob/master/private/sockets.nim#L97

また, #>flags -d:py3_version=3.5 -d:py3_dynamic でNimのコード(ここではセルで書いたもの)をコンパイルする際に渡すフラグを渡せるようです(下記のおまけも参照のこと). pye_version は各自のPythonのバージョンに合わせて変更してください.

手順4 実行

Shift+Enter で実行するとグラフがプロットされます.

めでたしめでたし.

おまけ1

Jupyter notebookを使わずにも描画機能を利用することができます.
例えば次のようなコードを書きます.

plottest.nim
import inim/pyplot

show:  
    plot(@[0.0,0.5,1],@[0.0,1,2],"b","--","o","dots")
    xlabel("dotssss")
    legend()
    plot(@[0.0,0.2,0.8],@[0.0,1,2],"r","-","o","dotsline")

コンパイルして実行します.この場合でもlibpython3.5.dylib が必要になります.

$ mkdir inimtemp
$ nim c -d:py3_version=3.5 -d:py3_dynamic plottest.nim
$ ./plottest 

実行結果は./inittemp 直下に保存されます. からかじめこのフォルダを mkdir しておかないとダメのようです.

おまけ2

static でビルドするときはおそらくですねPythonのヘッダーやライブラリのパスを教えないといけなさそうです.

--cincludes:DIR --clibdir:DIR --clib:LIBNAME とかをNimのコンパイルオプションに渡す必要があると思われます.

https://nim-lang.org/docs/nimc.html

注意したいのが static か dynamic かで呼び出するAPIの名前が異なるようなのでソースコードを追いかける必要があります. Exampleをみると dynamic の例が充実しているように思えます.

最後に

Nim 広めませう.