5分で学ぶ気になるプログラミング言語(Nim編)


※前回までの記事はこちらになります。あわせてご覧ください
5分で学ぶ気になるプログラミング言語(Rust編)
5分で学ぶ気になるプログラミング言語(Go編)

5分で学ぶNim

それでは今回は3部作の最後にNimを学んでいきます。
個人的には、Rust、Goに比べて殆ど事前知識がないので最も楽しみにしていた言語です。

Nimの公式サイトのURLは https://nim-lang.org/ です。
「Nim」という単語は意外にググラビリティがいいですね。語感もかわいい感じです。

NimもGoと同じく英語コンテンツのみのWebサイトです。デザインも何か硬派な感じですね。

他の言語と同じくファーストビューで特徴が語られていますが、
「Efficient, expressive, elegant」ということで、効率的で、表現力の豊かな、エレガントな言語であるとのことです。

続いて紹介文章があるのですが、静的型付けで、コンパイル型のシステムプログラミング言語であるとされています。Rust、Goと同じくコンパイル型ということで、時代のニーズを表している様に思います。また、Python、Ada、Modula等の成熟した言語から成功した概念を組み合わせたものとされており、いわゆるマルチパラダイムプログラミング言語としての特徴を持っている様です。

特徴である「expressive」の説明として、「Nim is self-contained: the compiler and the standard library are implemented in Nim.」と記載されています。Nimはコンパイラ機能と標準ライブラリがNimで記述されていることが分かりました。多くのプログラミング言語では、それらはC言語で開発されていることが多いわけですが、Nimはセルフホスティングという自分自身をコンパイルする機能を持っていることになります。

加えてよく見ると、「Support for various backends: it compiles to C, C++ or JavaScript so that Nim can be used for all backend and frontend needs.」という記述もあります。NimはC/C++/JavaScriptにコンパイルされる…? Nimのビルド方式は、いわゆるトランスコンパイル(他の言語用のソースコードに変換し、他の言語のコンパイラでビルドする)方式の様です。

なかなか興味深い作りですね~。

サイト上部のメニューを見渡すと「Documents」というリンクがありますのでクリックしてみます。

なんと、最初に「Learn Nim in 5 minutes」という、本連載と同じタイトルのコンテンツがあります(パクったみたいになっていますが…w)ちょっと見てみましょう。

クリックすると、 https://learnxinyminutes.com/docs/nim/ というURLに遷移しました。どうやら、5分で学ぶ的なコンテンツの集合体サイトの中の1つのコンテンツという位置付けの様です。

長いソースコードサンプルにコメントが書いていて、Nimの構文等が紹介されているスタイルです。この手のパターンはよくあるのですが、個人的にはあまり好きじゃないですね。普通に文法を淡々と紹介する形や、具体的な処理を題材に記述されていた方が分かりやすいかなと思います。

このサンプルコードを読んでいると、ソースコードのスタイルはPascalに似ているなぁと感じました。ファーストビューでの紹介で、AdaやModulaの概念を取り入れていると書いていましたので頷けます。

このコンテンツを5分やるのはもったいないので、次に「Nim basics tutorial」の方で学んでみます。

ソースコードの文法等については後で学ぶとして、「Testing the installation」でツールの使い方を覚えておきましょう。前回までと同様に、インストールは事前にパッケージマネージャで済ませておきます。

サンプルとしては、お馴染みのHello, Worldが紹介されているので書いてみます。

helloworld.nim
echo "Hello World!"

これだけ見るとかなり色々な言語でビルド出来そうな感がありますw

ビルドするにはシンプルに「c」オプションを付けてnimコマンドを実行する形です。

$ nim c helloworld.nim
Hint: used config file '/home/linuxbrew/.linuxbrew/Cellar/nim/1.6.0/nim/config/nim.cfg' [Conf]
Hint: used config file '/home/linuxbrew/.linuxbrew/Cellar/nim/1.6.0/nim/config/config.nims' [Conf]
.........................................................
CC: stdlib_digitsutils.nim
CC: stdlib_assertions.nim
CC: stdlib_dollars.nim
CC: stdlib_io.nim
CC: stdlib_system.nim
CC: helloworld.nim
Hint:  [Link]
Hint: gc: refc; opt: none (DEBUG BUILD, `-d:release` generates faster code)
26565 lines; 1.411s; 31.613MiB peakmem; proj: /home/kansaizine/helloworld.nim; out: /home/kansaizine/helloworld [SuccessX]

デフォルトでは、ソースコード名から拡張子を除いた名前でバイナリが生成される様なので、それを直接実行すればOKです。

$ ./helloworld
Hello, World!

「-r」オプションを付けると、バイナリを生成した後、実行まで行ってくれます。簡単ですね。

$ nim c -r helloworld.nim
Hint: used config file '/home/linuxbrew/.linuxbrew/Cellar/nim/1.6.0/nim/config/nim.cfg' [Conf]
Hint: used config file '/home/linuxbrew/.linuxbrew/Cellar/nim/1.6.0/nim/config/config.nims' [Conf]
.........................................................
Hint:  [Link]
Hint: gc: refc; opt: none (DEBUG BUILD, `-d:release` generates faster code)
26565 lines; 0.711s; 31.652MiB peakmem; proj: /home/kansaizine/helloworld.nim; out: /home/kansaizine/helloworld [SuccessX]
Hint: /home/kansaizine/helloworld  [Exec]
Hello, World!

最後に、コマンドのオプション等を調べておきましょう。

$ nim
Nim Compiler Version 1.6.0 [Linux: amd64]
Compiled at 2021-10-19
Copyright (c) 2006-2021 by Andreas Rumpf
::

    nim command [options] [projectfile] [arguments]

Command:
    compile, c              compile project with default code generator (C)
    r                       compile to $nimcache/projname, run with [arguments]
                            using backend specified by `--backend` (default: c)
    doc                     generate the documentation for inputfile for
                            backend specified by `--backend` (default: c)

Arguments:
  arguments are passed to the program being run (if --run option is selected)

Options:
  -p, --path:PATH           add path to search paths
  -d, --define:SYMBOL(:VAL)
                            define a conditional symbol
                            (Optionally: Define the value for that symbol,
                            see: "compile time define pragmas")
  -u, --undef:SYMBOL        undefine a conditional symbol
  -f, --forceBuild:on|off   force rebuilding of all modules
  --stackTrace:on|off       turn stack tracing on|off
  --lineTrace:on|off        turn line tracing on|off
  --threads:on|off          turn support for multi-threading on|off
  -x, --checks:on|off       turn all runtime checks on|off
  -a, --assertions:on|off   turn assertions on|off
  --opt:none|speed|size     optimize not at all or for speed|size
                            Note: use -d:release for a release build!
  --debugger:native         Use native debugger (gdb)
  --app:console|gui|lib|staticlib
                            generate a console app|GUI app|DLL|static library
  -r, --run                 run the compiled program with given arguments
  --eval:cmd                evaluates nim code directly; e.g.: `nim --eval:"echo 1"`
                            defaults to `e` (nimscript) but customizable:
                            `nim r --eval:'for a in stdin.lines: echo a'`
  --fullhelp                show all command line switches
  -h, --help                show this help
  -v, --version             show detailed version information

Note, single letter options that take an argument require a colon. E.g. -p:PATH.

基本的にコンパイルと実行だけで、後はデバッグ系のオプション等がある感じですね。
非常にシンプルな作りで、覚えることが少なくて済むのは良いことだと思いました。

学べたこと

楽しみにしていたNimについて、下記のことが分かりました。

Nimもコンパイラ型言語である

Nimは、RustやGoと同様に、ソースコードを記述してそれをnimコマンドで直接実行もできつつ、コンパイルして実行バイナリを生成することもできる、コンパイラ型言語であることが分かりました。システムプログラミング言語としては必須の特徴になっていくのかなと思います。

Nimはトランスコンパイルの仕組みを持っている

Nimは、Nim言語として記述されたソースコードを、C/C++/JavaScript等のソースコードに変換してから最終的にバイナリ化する仕組みとなっている様です。変換精度が気になるところですが、その辺りは追って調べてみたいと思います。

Nimは公式の学習コンテンツが充実している

今回見てみたコンテンツの他、チュートリアルやリファレンス、C等との連携方法等、ドキュメントは充実しており、読みごたえもありそうです。英語コンテンツだけなので若干の英語力は必要です。Playgroundも用意されているので、ブラウザがあればNimのソースコードを記述して、オンラインで実行させることも可能です。

最後に

Rust、Go、Nim と気になる言語3つを学んできましたが、コンパイラ型という共通項はあるものの、各言語とも特徴があり、人気のある理由がうかがえました。RustやGoはWeb等にもよく使われているイメージですが、Nimにもフレームワークがある様で、適用範囲もシステムプログラミングからWebまで広く適用できるということで、どれを学んでも損はないのではないかと感じました。

そんな私ですが…、直感でGoを学びたいと思います!

やはりGoogleって憧れがありますし… Kubernetes、docker、Terraform等がGoで書かれているとか、私の業務領域には最も合っている様な気がしました。でもRustもNimも気になるから、結局最終的には全部使うと思います!w

5分で学ぶのは若干無理があったのは事実ですが、そうやって何かしらルールを作って取り組んでみるのも工夫の一つだと考えています。3部作はいったん終了しますが、また違う題材で同じ様にやってみたいなと思います。

お読みいただいてありがとうございました。