Features

Intuitive and clean syntax.

Taking inspiration from multiple languages, the Nim syntax is easily understood and results in code that can be modified very efficiently.

  • Indentation significant syntax
  • Multiple constructs inspired by Python
  • Multi-line lambdas
  • Oberon-inspired visibility markers
  • Pascal-inspired type sections for leaner definitions
import strutils
type
  Person = object
    name*: string # Field is exported using `*`.
    age: Natural  # Natural type ensures the age is positive.

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

for person in people:
  echo("$1 is $2 years old" % [person.name, $person.age])

Support for multiple operating systems

Nim supports every mainstream operating system and platform as well as multiple niche platforms. We take pride in supporting all three major operating systems fully.

Many garbage collector options.

Choose from a deferred RC'ing garbage collector that is fast, incremental and pauseless; or a soft real-time garbage collector that is deterministic allowing you to specify its max pause time; and many others.

Native performance with state of the art optimisations

By compiling to C, Nim is able to take advantage of many features offered by modern C compilers. The primary benefits gained by this compilation model include incredible portability and optimisations, which have been implemented over more than 40 years by various individuals and influential companies.

The binaries produced by Nim have zero dependencies and are typically very small. This makes their distribution easy and keeps your users happy.

JavaScript compilation.

Nim includes a first-class JavaScript backend so you can target the client and server effortlessly at the same time.

New Game: N Play/Pause: P Controls: ← → ↑ ↓

The above game is written in Nim, compiled using the JavaScript backend and drawn using the canvas API.

Source code: https://github.com/dom96/snake

Game website: 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

Small core with a rich prospect for extensibility

Nim implements a small core language with a powerful set of metaprogramming features.

The metaprogramming features in Nim include support for generics, templates, and macros. This allows Nim to be extended with support for various programming paradigms and allows developers to avoid boilerplate. The standard library implements async await using these metaprogramming features and the Nim community has developed various packages implementing different programming paradigms.

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

Decentralised package management.

The Nim package manager is called Nimble. Packages are distributed via Git and Mercurial repositories, and tags are queried remotely to determine version information.

A mapping between package names and repository URLs is defined in a packages.json file that is stored on GitHub.

Packages are defined using a specially formatted .nimble file that is evaluated by the Nim compiler. This means that it supports a large subset of the Nim programming language, allowing various powerful features including the ability to determine the OS and specify external dependencies.

# Package

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

# Dependencies
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"

Easy C, C++ and Objective C wrapping

{.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>".}

proc videoMode*(modeWidth, modeHeight: cuint,
                modeBitsPerPixel: cuint = 32): VideoMode
    {.importcpp: "sf::VideoMode(@)", constructor.}

proc newRenderWindow*(mode: VideoMode, title: cstring): RenderWindow
    {.importcpp: "new sf::RenderWindow(@)", constructor.}

proc pollEvent*(window: RenderWindow, event: var Event): bool
    {.importcpp: "#.pollEvent(@)".}

proc newColor*(red, green, blue, alpha: uint8): Color
    {.importcpp: "sf::Color(@)", constructor.}

proc clear*(window: RenderWindow, color: Color)
    {.importcpp: "#.clear(@)".}

proc display*(window: RenderWindow)
    {.importcpp: "#.display()".}

Nim makes it easy to bind to C, C++ and Objective C libraries. This allows developers to easily access a large ecosystem of mature and powerful libraries.

Helpful tracebacks.

Inspired by Python. When a Nim application crashes with an exception, it will output a stack trace before terminating. The format of this stack trace is very easy to grasp and contains all the required information to debug the exception.

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