コンテンツにスキップ

Nim Cheat Sheet

Overview

Nim is a statically-typed compiled systems programming language that combines the performance of C with the expressiveness of Python. It features a clean, indentation-based syntax, a powerful macro system for metaprogramming, and compiles to C, C++, JavaScript, or Objective-C. Nim’s memory management options range from a traditional garbage collector to deterministic destructors (ARC/ORC), giving developers fine-grained control over performance characteristics.

Created by Andreas Rumpf in 2008, Nim has evolved into a versatile language suitable for systems programming, web development, scripting, and game development. Its compile-time code execution, generic programming, and template system enable zero-cost abstractions. Nim’s standard library is comprehensive, and its package manager Nimble provides access to thousands of community packages. The language prioritizes efficiency, expressiveness, and elegance.

Installation

Package Managers

# macOS
brew install nim

# Ubuntu/Debian
apt install nim

# Windows (scoop)
scoop install nim

# Using choosenim (version manager, recommended)
curl https://nim-lang.org/choosenim/init.sh -sSf | sh
choosenim stable

Verify Installation

nim --version
nimble --version

# Compile and run
nim c -r hello.nim       # Compile C backend + run
nim cpp -r hello.nim     # Compile C++ backend + run
nim js hello.nim         # Compile to JavaScript

Core Language

Variables and Types

# Immutable (let) and mutable (var)
let name = "Nim"           # Inferred as string
let pi: float = 3.14159
var counter = 0
counter += 1

# Constants (compile-time)
const MaxSize = 1024
const Version = "1.0.0"

# Basic types
let i: int = 42
let f: float64 = 3.14
let b: bool = true
let c: char = 'A'
let s: string = "hello"

Primitive Types

TypeDescriptionExample
intPlatform-sized integer42
int8 to int64Sized signed integers42'i32
uint8 to uint64Sized unsigned integers255'u8
float32, float64Floating point3.14
boolBooleantrue, false
charSingle character'A'
stringMutable string"hello"
cstringC-compatible stringcstring"hello"
seq[T]Dynamic array@[1, 2, 3]
array[N, T]Fixed-size array[1, 2, 3]

Control Flow

# If/elif/else
if x > 0:
  echo "positive"
elif x == 0:
  echo "zero"
else:
  echo "negative"

# Case statement (exhaustive for enums)
case command
of "start": startServer()
of "stop": stopServer()
of "status": showStatus()
else: echo "Unknown command"

# When (compile-time if)
when defined(windows):
  echo "Windows"
elif defined(linux):
  echo "Linux"
else:
  echo "Other OS"

# For loops
for i in 0..9:
  echo i

for i in countup(0, 10, 2):    # Step by 2
  echo i

for item in items:
  echo item

for i, item in items:            # With index
  echo i, ": ", item

# While loop
var n = 10
while n > 0:
  echo n
  dec n

Procedures and Functions

# Procedure (may have side effects)
proc greet(name: string): string =
  result = "Hello, " & name & "!"

# Function (no side effects)
func add(a, b: int): int =
  a + b

# Default parameters
proc connect(host: string, port: int = 8080, ssl: bool = false) =
  echo "Connecting to ", host, ":", port

# Varargs
proc sum(args: varargs[int]): int =
  for x in args:
    result += x

echo sum(1, 2, 3, 4)  # 10

# Overloading
proc display(x: int) = echo "Int: ", x
proc display(x: string) = echo "Str: ", x

# Method call syntax (UFCS)
"hello".len        # Same as len("hello")
@[3,1,2].sorted    # Same as sorted(@[3,1,2])

# Result variable (implicit return)
proc factorial(n: int): int =
  result = 1
  for i in 2..n:
    result *= i

Collections

# Sequences (dynamic arrays)
var nums = @[1, 2, 3]
nums.add(4)
nums.delete(0)
echo nums[^1]          # Last element
echo nums[1..2]        # Slice

# Arrays (fixed size)
var arr: array[5, int] = [1, 2, 3, 4, 5]

# Tables (hash maps)
import std/tables
var users = initTable[string, int]()
users["alice"] = 30
users["bob"] = 25

if users.hasKey("alice"):
  echo users["alice"]

for key, value in users:
  echo key, ": ", value

# Sets
import std/sets
var s = initHashSet[int]()
s.incl(1)
s.incl(2)
echo 1 in s  # true

# Tuples
let point = (x: 10, y: 20)
echo point.x
let (a, b) = (1, "hello")

Object-Oriented Features

# Object types
type
  Animal = ref object of RootObj
    name: string
    age: int

  Dog = ref object of Animal
    breed: string

  Cat = ref object of Animal
    indoor: bool

# Methods
method speak(a: Animal): string {.base.} =
  "..."

method speak(d: Dog): string =
  "Woof!"

method speak(c: Cat): string =
  "Meow!"

# Enum types
type
  Color = enum
    Red, Green, Blue

  Direction = enum
    North = "N"
    South = "S"
    East = "E"
    West = "W"

# Distinct types (newtypes)
type
  Dollars = distinct float
  Euros = distinct float

Error Handling

# Exceptions
try:
  let data = readFile("config.txt")
  echo data
except IOError as e:
  echo "IO Error: ", e.msg
except:
  echo "Unknown error"
finally:
  echo "Cleanup"

# Raising exceptions
proc divide(a, b: float): float =
  if b == 0:
    raise newException(DivByZeroDefect, "Division by zero")
  a / b

# Option type
import std/options
proc findUser(name: string): Option[string] =
  if name == "admin":
    some("Admin User")
  else:
    none(string)

let user = findUser("admin")
if user.isSome:
  echo user.get()

Build and Package Management

Nimble (Package Manager)

# Create new project
nimble init myproject

# Install package
nimble install jester
nimble install karax

# Build project
nimble build

# Run project
nimble run

# List installed packages
nimble list --installed

# Search packages
nimble search http

Compilation Options

CommandDescription
nim c -r main.nimCompile (C) and run
nim c -d:release main.nimRelease build (optimized)
nim c -d:danger main.nimMaximum optimization (no checks)
nim c --mm:orc main.nimUse ORC memory management
nim c --mm:arc main.nimUse ARC memory management
nim c --threads:on main.nimEnable threading
nim c --opt:speed main.nimOptimize for speed
nim c --opt:size main.nimOptimize for size
nim js main.nimCompile to JavaScript

Configuration

nim.cfg / config.nims

# config.nims
switch("mm", "orc")
switch("threads", "on")
switch("d", "ssl")

when defined(release):
  switch("opt", "speed")
  switch("passC", "-flto")

# Task definitions
task build, "Build the project":
  exec "nim c -d:release src/main.nim"

task test, "Run tests":
  exec "nim c -r tests/test_all.nim"

Advanced Usage

Templates and Macros

# Templates (inline code substitution)
template `!=`(a, b: untyped): bool =
  not (a == b)

template withFile(f, filename, mode, body: untyped) =
  var f: File
  if open(f, filename, mode):
    try:
      body
    finally:
      close(f)
  else:
    raise newException(IOError, "Cannot open: " & filename)

withFile(file, "data.txt", fmRead):
  echo file.readAll()

# Macros (AST transformation)
import std/macros

macro dumpTree(body: untyped): untyped =
  echo body.treeRepr
  body

macro createEnum(name: untyped, fields: varargs[untyped]): untyped =
  result = nnkTypeSection.newTree(
    nnkTypeDef.newTree(name, newEmptyNode(),
      nnkEnumTy.newTree(newEmptyNode())))
  for field in fields:
    result[0][2].add(field)

Async/Await

import std/asyncdispatch

proc fetchData(url: string): Future[string] {.async.} =
  let client = newAsyncHttpClient()
  let response = await client.getContent(url)
  return response

proc main() {.async.} =
  let data = await fetchData("https://api.example.com/data")
  echo data

waitFor main()

FFI (C Interop)

# Import C functions
proc printf(format: cstring): cint {.importc, varargs, header: "<stdio.h>".}

# Wrap C library
{.passL: "-lsqlite3".}
type Sqlite3 = distinct pointer

proc sqlite3_open(filename: cstring, db: ptr Sqlite3): cint
  {.importc, header: "<sqlite3.h>".}

Troubleshooting

ProblemSolution
undeclared identifierCheck import statements; Nim is case-insensitive but underscore-insensitive
type mismatchUse explicit type conversion; check proc signatures
GC pausesSwitch to ARC/ORC with --mm:orc
Slow compilationUse --incremental:on; split into modules
C codegen issuesCheck generated C in nimcache/; use {.emit.} pragma
JS backend differencesSome stdlib modules not available; check docs
Memory leaksUse --mm:orc for cycle collection; check ref objects
SIGSEGVCheck nil dereferences; use --panics:on for better traces