特徴

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

さまざまな言語からインスピレーションを得ているため、 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 はプラットホームとして、すべての主要オペレーティングシステム、および様々なニッチプラットホームにも サポートしています。三大オペレーティング・システムを 完全サポートしていることを誇りに思います。

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]

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