特徴

直感的で美しいシンタックス

複数の言語からインスピレーションを得ているため、 Nim のシンタックスは理解が容易あり、 コードの修正は非常に効率的なものとなります。

  • インデントに意味を持たせたシンタックス
  • Python に影響を受けた多重コンストラクタ
  • 複数行ラムダ
  • Oberon に影響を受けた可視性マーカー
  • Pascal に影響を受けた効率的な定義ができる型階層 (type sections)
import strformat
type
  Person = object
    name*: string # フィールドは `*` でエクスポートします。
    age: Natural  # Natural 型の age を正数として確保します。

var people = [
  Person(name: "John", age: 45),
  Person(name: "Kate", age: 30)
]

for person in people:
  # 型安全の文字列補完。
  echo(fmt"{person.name} is {person.age} years old")

各種オペレーティング・システムへのサポート

Nim はプラットホームとして、すべての主要オペレーティングシステム、および様々なニッチプラットホームにも サポートしています。三大オペレーティング・システムを 完全サポートしていることを誇りに思います。

豊富なガーベジコレクターの選択肢

高速、逐次的であり、一時停止処理のない遅延 RC'ing ガーベジ・コレクター、あるいは、最大一時停止時間を指定できる 柔軟なリアルタイムガーベジ・コレクター。 それ以外にも様々な方法を選べます。

最先端の最適化技法によるネイティブ・パフォーマンスを実現

Cへのコンパイルにより、 最新のCコンパイラに備わっている様々な機能を Nim で享受できます。 このコンパイル方式の最大の利点は、素晴らしい移植性と最適化などがあります。 これらは大勢の個人と有力企業により、 40年以上に渡って実装が続けられてきました。

Nim で生成したバイナリは依存性がなく、通常は超小型軽量になります。 これにより、配布は簡単になるため、 ユーザの満足度が高まります。

JavaScript へのコンパイル

Nim には、素晴らしい JavaScript バックエンドが搭載されているため、 苦労せずにクライアントとサーバを同時にターゲットにできます。

ゲーム開始: N 再開/一時停止: P 操作: ← → ↑ ↓

上述のゲームは Nim で記述してあります。 コンパイルは JavaScript バックエンド、描画は Canvas API です。

ソースコード: https://github.com/dom96/snake

ゲームのウェブサイト: http://picheta.me/snake

import dom

proc onLoad(event: Event) =
  let p = document.createElement("p")
  p.innerHTML = "Click me!"
  p.style.fontFamily = "Helvetica"
  p.style.color = "red"

  p.addEventListener("click",
    proc (event: Event) =
      window.alert("Hello World!")
  )

  document.body.appendChild(p)

window.onload = onLoad

豊かな可能性を秘めた拡張性のある小規模コア

Nim には強力なメタプログラミング機能一式を 備えた小規模コア言語を実装しております。

Nim のメタプログラミング機能はジェネリック、テンプレートとマクロなどに対応しています。 これにより、各種プログラミング・パラダイムに対応することで Nim の拡張を可能にし、 開発者はボイラープレートを書かなくて済むようになります。 標準ライブラリ async await (非同期待機) はメタプログラミング機能を用いて実装しております。 また、 Nim コミュニティでは様々なプログラミング・パラダイムを 実装してパッケージを色々と開発しています。

import macros, strutils

macro toEnum(words: static[string]): untyped =
  result = newTree(nnkEnumTy, newEmptyNode())

  for w in splitWhitespace(words):
    result.add ident(w)

type
  Color = toEnum"Red Green Blue Indigo"

var color = Indigo

分散パッケージ管理

Nim パッケージマネージャの名前は Nimble です。 パッケージは Git と Mercurial リポジトリで配布されており、 バージョン情報を決定するためにネット経由でタグを照会します。

パッケージ名とリポジトリ URL との対応付けは GitHub に収録されている packages.json ファイルに定義されています。

パッケージは専用形式の .nimble ファイルへ定義します。 このファイル形式は Nim コンパイラにより評価されます。 つまり、オペレーティングシステムの決定と外部依存性の指定ができるなど 豊富で強力な機能を実現するため、プログラミング言語 Nim で広大なサブセットをサポートできます。

# パッケージ

version       = "v0.1.0"
author        = "Benedict Cumberbatch"
description   = "Sample package."
license       = "MIT"

# 依存性
requires "nim >= 0.13.0", "jester >= 0.1.0"

import distros
if detectOs(Ubuntu):
  foreignDep "libssl-dev"
else:
  foreignDep "openssl"

task test, "Run the tester!":
  withDir "tests":
    exec "nim c -r tester"

容易な C, C++ Objective C とのラッピング

{.passL: "-lsfml-graphics -lsfml-system -lsfml-window".}

type
  VideoMode* {.importcpp: "sf::VideoMode".} = object
  RenderWindowObj {.importcpp: "sf::RenderWindow".} = object
  RenderWindow* = ptr RenderWindowObj
  Color* {.importcpp: "sf::Color".} = object
  Event* {.importcpp: "sf::Event".} = object

{.push cdecl, header: "<SFML/Graphics.hpp>".}
{.push importcpp.}

proc videoMode*(modeWidth, modeHeight: cuint,
                modeBitsPerPixel: cuint = 32): VideoMode
proc newRenderWindow*(mode: VideoMode, title: cstring): RenderWindow
proc pollEvent*(window: RenderWindow, event: var Event): bool
proc newColor*(red, green, blue, alpha: uint8): Color
proc clear*(window: RenderWindow, color: Color)
proc display*(window: RenderWindow)

Nim は C, C++ と Objective C ライブラリとの接続が簡単です。 これにより、開発者は広大で成熟したエコシステムと 強力なライブラリへ容易にアクセスできるようになります。

実用的なトレースバック

Python に影響を受けています。

例外で Nim アプリケーションがクラッシュするとき、 終了前にスタックトレースを出力します。 このスタックトレースの書式は非常に理解しやすく、 例外のデバッグで必要な全情報を記載してあります。

Traceback (most recent call last)
module.nim(10)           module
module.nim(8)            readData
strutils.nim             parseInt
Error: unhandled exception:
       invalid integer: Hello World [ValueError]

ほかに質問はございますか? よくある質問と回答をご覧ください。