14
11

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.

(年明けから)Pythonと共にNimを学ぶ。

Last updated at Posted at 2016-12-14
本日は、実務でC++/objective-cを淡々と使っていたり,Pythonistaだったりする兄貴たちに向け、Nimと共にPythonを学んでいる自分のメモ書きを晒す。 ...年明けから、Python+Cで,デカいデータを相手にする仕事するんですよね。nim使ってもバレなそうな気もちょっとしていて、ありがたや、ありがたや。

コンパイル言語Nim(旧Nimrod)の特徴をひとつ

2008年頃から開発が続く、旧NimrodことNim。
Python使いの人にその特徴を捉えてもらうには、wikipedia日本語版のnimのところに記されている以下のコードを見ていただくのが良いのではないかと考える。

wikipedia.nim
proc reverse(s: string): string =
  result = "" # 暗黙的なresult変数
  for i in countdown(high(s), 0):
    result.add s[i]

var str1 = "Reverse This!"
echo "Reversed: ", reverse(str1)

wikipediaの解説を少し噛み砕くと :

  • 暗黙的なresult変数に注目。Nimでは、returnの型がvoidではないプロシージャは、暗黙的なresult変数を持つ。result変数はプロシージャの返り値を保持している。
  • forループでのcountdownはイテレータである。ここでは、high(s)により得られる文字列長から0へと、1ずつカウントダウンされるイテレータが記述されている。

Nimは型ありコンパイル言語ながら、スクリプト言語っぽく書くことができる。

国内でNimが知られ始めたのは、Takano32氏による「Nimrod で FizzBuzz を書こう!」という5年ほど前のブログあたりからではないかと考えられる。

RubyコミッターであるTakano32氏は、その後、さっそくに「なんと Nimrod で Python が使えるの!?」というエントリーを投稿している。

そう、pythonとnimとを併用しようという人々はけっこういる(rubyとnimとの関係はどうなんだろ?)。

ということで、今回は、pythonからnimを呼び出してみて、その使いどころを考えておきたい。

*で、馬並み、でなくてC言語並みの実行速度を持つnimに興味を持ったpython使いの方々は、nimのソースコードと本家のドキュメントなとをガンガン読み解いて、ブログにアップしてください。私が助かる^_^*

#pythonからnimを呼び出す。

基本的なところは、Connecting Nim to Pythonに従えば、あっという間。
やっていることは、nimのソースコードから、C言語のいわゆる共有ライブラリを作り出すこと。バイナリは実行環境依存となる。以下、Macでの事例。xcodeと最新のbrewが入っている環境ならば、nimのインストールは以下だけで良い。

brew install nim

まずはプロシージャ(関数)ひとつだけのnimコードを用意し、

fn1.nim
proc summer*(x, y: float): float {. exportc, dynlib .} =
  result = x + y

以下で、共有ライブラリ化する。

nim c --app:lib fn1.nim

生成されたlibfn1.dylibを呼び出すpythonコードは以下となる(Macに最初から入っているpython2.7を使用)。C言語の共有ライブラリ呼び出しなので、ctypesを使う。

py2nim1.py
from ctypes import *

def main():
    test_lib = CDLL('./libfn1.dylib')

    # Function parameter types
    test_lib.summer.argtypes = [c_double, c_double]

    # Function return types
    test_lib.summer.restype = c_double

    sum_res = test_lib.summer(1.0, 3.0)
    print('The sum of 1.0 and 3.0 is: %f'%sum_res)

if __name__ == '__main__':
    main()

64bit環境ではdouble型にするのに注意すれば、『4.0』という答が,nimから得られる。

使い所は,例えば社内のバッチ処理システムなど、か。

numpy, pypy, micropython, R18python...などなど卑猥なでなくて、実行速度を追い求め専門的なpy用語が飛び交う環境ならば、nimはすんなりと溶け込めるかもしれない。
そうでなくとも、『おい、お前、これを見ろ。こいつをどう思う』--「すごく、大きいです...(計算量的に)」といった環境が目の前にあるならば、python+C系言語+nimで、処理に挑むのはありうる話だと思われる。

マイナー言語であった20年くらいから,猛者たちによって無数のコードが書かれてきたpythonには,さまざまな『芸』がある。例えば、Mac環境にはPyObjCなるObjective-c(++)の呼び出しライブラリが入っていて、pythonでObjective-cで書かれたGUIを呼び出しつつ、nimも呼びだすなんてことがすぐにできる。
python側のGUI呼び出し記述が長いので、コードはgistに置いておく。

実行例:
スクリーンショット 2016-12-15 05.12.54.png

nimで書かれた計算ライブラリを呼び出すユーザー向けのGUIを作り出すなんてのは、pythonを使えば、手間がぐっと減る。コンパイル言語であるnimは、適宜、親和性の高いC/C++を呼び出すデータ処理記述に専念できるわけだ。

#続く

...と、今はネタ言語にとどまるnimについて、割合と常識的なことを書いてしまった。が、兄貴、ご安心を。これを出発点に、近々、IoTをお題としたネタ投稿を書きまする。

14
11
0

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
14
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?