Nimを知ってほしい


なんでこんなのを書いているのか

Nimを趣味で使っているのですが、「Nim?なにそれ?」みたいな話を何度もするのが疲れたのでURL投げつければ済むようにしたいからです。
F#を知ってほしいに敬意を。
※Nim使いの人もマサカリ(というかアドバイス)とかあればください。
※Nimの概説が面倒なときに参照先として使ってください。
※medyさんの記事Nimを知ってほしい2022もオススメです。

Nimとは, なぜNimなのか

ざっくりと説明すると、
静的型付けで型安全な上にPythonっぽい構文でコード量も少なく済む「効率的、表現力豊か、エレガント」なプログラミング言語です。
コンパイラが優秀すぎて、勝手に最適化して実行バイナリのサイズを小さくしてくれるし速い。
誤解を恐れずに表現するなら「Pythonの皮を被ったC/C++」。

詳細はWikipedia読んだほうがいいです。引用(https://ja.wikipedia.org/wiki/Nim)

Nimはシンプルな構文による静的型付け言語である[9]。構文マクロや項書き換えマクロなどのコンパイル時のメタプログラミング機能をサポートしている[10]。項書き換えマクロは例えばBignumやMatrixなどのデータ構造の効率的ライブラリ実装を可能にしており、BignumやMatrixなどがあたかも元々の言語機能に組み込まれていたかのような効率的な実装を可能にする[11]。イテレータもサポートしており、このイテレータはNimの中で第一級オブジェクトとして用いることができ[10]、これら機能は関数プログラミングを可能にする。オブジェクト指向プログラミングは継承と多重ディスパッチによってサポートされている。関数はジェネリックになりうるし、オーバーロードも可能である。またTypeクラスがサポートされており、これはジェネリクスを促進するものである。演算子オーバーロードもサポートされている[10]。Nimは循環参照検出つきの遅延参照カウントに基づくガベージコレクタを搭載している[12][13]。アンドリュー・ビンストック[14]はNimに関して「(Nimは)PascalおよびPythonにまたがる非常に独創的なデザインを提供し、CやJavaScriptのコードにコンパイルすることができる[15]」と述べた。

「書いていてしっくりきたし、不便がない」というのがNimを使っている一番の理由です。
コードを見たほうがよく分かると思うので、100 doorsのコードを以下から引用(http://rosettacode.org/wiki/100_doors#Nim)

from strutils import format

var isOpen: array[1..100, bool] 
for pass in countup(1, 100):
  for door in countup(pass,100,pass):
    isOpen[door] = not isOpen[door]
 
for i in countup(1, 100):
  if isOpen[i]:
    echo("Door ",i," is open.")

Pythonっぽい!!

ちなみにNimは「効率的、表現力豊か、エレガント」を意識しています。
この思想が個人的にしっくりきた理由です。
ここからはもう少し具体的な話をしたいと思います。

1. Efficient

効率の面で、Nimは仮想マシン(JVMやCLR等)に依存しないネイティブな実行可能ファイルをマルチプラットフォーム向けに生成することができます。
細かい話をすると、Nimはコードを裏でC(C++,JS)にトランスコンパイルしてから指定されたCコンパイラでビルドして実行可能ファイルを生成しています。このトランスコンパイル時の最適化が優秀で、Nimが速いと言われている理由です。
Nimのおかげである程度のレベルまでは最適化がされますが、NimのトランスコンパイルしたCのソースコードに手を加えれば更に最適化ができます。がそのようなケースは稀だと思います

ちなみにNimは多くのプラットフォームをサポートしているようで、ターゲットOSの中にはLinux/Windows/macOSやandroid/iphoneだけでなくnintendoswitchもあります。がそのようなケースは稀だと思います

詳しくはコンパイラユーザーズガイドを参照してください。
https://nim-lang.org/docs/nimc.html
※いないとお思いますがnintendoswitchで動作確認した人がいたら記事でも書いてください

2. Expressive

Nimはシンプルな構文でありながら表現力が豊かで、書いていて気持ちがいいです。
というのもNimのマクロはASTを直接操作でき、DSLっぽい何かを作ることができます。
※別にNimにしかない機能ではありません。C++使いはメタプロで馴染みがありそう。

例としてjesterというweb frameworkのコードではrouterマクロにより、記述が簡素になっています。

import asyncdispatch, jester, os, strutils

router myrouter:
  get "/":
    resp "It's alive!"
  post "/":
    var push = parseJson(@"payload")
    resp "I got some JSON: " & $push

proc main() =
  let port = paramStr(1).parseInt().Port
  let settings = newSettings(port=port)
  var jester = initJester(myrouter, settings=settings)
  jester.serve()

when isMainModule:
  main()

3. Elegant

エレガントな点についてはオフサイドルールとか色々あるのですが、
個人的に一番エレガントだなと思ったのは糖衣構文で第一引数の型に関数がバインドされる機能です。
https://nim-lang.org/docs/tut2.html#object-oriented-programming-method-call-syntax

D言語とかだとUniform Function Call Syntaxと呼ばれてるみたいです。
https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax

proc add(a: int, b: int): int =
  a + b

var num: int = 10
echo add(num, 5)
echo num.add(5) #int型にaddがバインドされているのでこうやって呼び出せる
#num = 15

関数をつなげるためにfunc(func(..))みたいなネストを避けて、型安全なメソッドチェーンで記述でき、
既存の型の拡張メソッドが作りやすいので、とても気に入っています。

質問とか

Q.なかなかメジャーバージョン1.0がリリースされないって聞いたけど?

A. 待ちに待った1.0.0が2019/9/23にリリースされました。

公式ブログ:https://nim-lang.org/blog/2019/09/23/version-100-released.html
今後は安定したバージョンで開発することができます。

Q.ドキュメントとか少ないのでは?

A. 確かに日本語ドキュメントは少ない。けど英語ドキュメントは豊富だし親切

英語が苦手だと大変ですが、Google翻訳使いながらでも十分探せます。
というかこの手のドキュメントは日本語にしたほうが難解になると個人的には思っています。
また、公式サイトのLearnページは様々なトピックがあり、いろいろな学びの始め方を用意してくれているのでとても親切だと思います。
私はNimのおかげで英語ドキュメント読む機会が増えて苦手意識がなくなりました。

Q.ライブラリが少ないのでは?

A. 確かに他言語と比べると少ないかも。けど、CやC++のライブラリが使えるから困らない

個人的には十分あると思いますが、多言語と比べると選択肢が確かに少ない気がします。
今後、Nim使いが増えてライブラリの種類も増えることに期待しましょう。
ちなみに以下でパッケージが探せます。
https://nimble.directory/

Q. 将来性がないのでは?

A. 未来のことはわからないが、毎月$19,000支援している企業がいるので大丈夫では?

ちなみに将来はCやC++をRustが置き換えていくみたいな話がありますが、
もしそうなると、NimはCやC++と同様にバックエンドにRustを加えてしぶとく生き残るのではないかなと思います。 できるのかどうかは別として
フォーラムでも少し話題になりましたし。
https://forum.nim-lang.org/t/2688

Nimを始めるには

【追記】
樅山さんが学習ロードマップでいい感じにまとめてくれているので参考になります。
樅山さんをフォローしておけば、初学者には有益な情報がたくさん入ってくると思います。


公式には色々なLearnドキュメントがありますが、Pythonを書いたことがある人は下記のNim-For-Python-Programmersから始めればNimで動くコードがすぐに書けるようになると思います。 その上でプラグマなどNimをより知るために公式チュートリアルやを一通り読んで理解を深めると良いかもしれません。Nim in Actionのプログラムは公開されているのでそれを読むのもオススメです。

Nim-for-Python-Programmers
Nim-for-TypeScript-Programmers
Nim-for-C-programmers

おまけ

Nim公式で紹介しているいくつかの資料を載せておきます。

1. ガベージコレクションとメモリ


Source: https://forum.nim-lang.org/t/2646/3#18263

2. バイナリサイズ


Source: https://github.com/dom96/binary_size

3. Nim Community Survey 2019 Results

Nimコミュニティ向けに行われた調査結果が2020/2/18に公開されました。
Nimユーザの多くは、Nimを第二言語のように使っているケースが多いようです。
個人的にはjs関連の改善に期待しています。