Nim Language Overview

Nim 2.2 — systems language | Python-like syntax | C/JS/LLVM backends | GC optional | metaprogramming via macros

Paradigm

Multi-paradigm: imperative, functional, object-oriented (via method call syntax), metaprogramming. Static typing with full inference (Hindley-Milner-like), structural type equivalence. Compilation via C, C++, JavaScript, or LLVM. AST-based macros run at compile time.

Types

Category Types
Signed int int8 int16 int32 int64 int (platform-dependent)
Unsigned int uint8 uint16 uint32 uint64 uint
Float float32 float64
Bool bool
Char char (1 byte)
String string (mutable, length-prefixed)
C string cstring (null-terminated)
Array array[N, T] array[T]
Sequence seq[T] (dynamic array, GC-managed)
Tuple (T1, T2) / tuple[a: T1, b: T2]
Object object / ref object (heap + GC by default)
Enum enum { variant, variant2 }
Range range[0..100] (subrange)
Set set[T] (bitfield, up to 256 elements)
Pointer ptr T
Reference ref T (GC-traced)
Optional Option[T] (from std)
Result Result[T, E]
Distinct distinct T (newtype wrapper)
Type class Concept/generic constraint
Void void (return type)
Never never (diverging)

Declarations

Construct Syntax Notes
Function proc name(params): Ret = body
Method proc name(self: T; params): Ret = body
Template template name(params): untyped = body AST substitution
Macro macro name(params): untyped = body AST manipulation
Variable let x = expr Immutable
Mutable var x = expr
Constant const NAME = expr Compile-time
Let (runtime) let x: T = expr
Object type Name = object Value type
Ref object type Name = ref object Heap-allocated
Tuple type Name = tuple[a: T, b: U]
Enum type Name = enum { a, b, c }
Union type Name = object { case tag: T of ... } Variant/SUM type
Type alias type Name = T
Import import module / from module import name
Include include "file.nim" Textual inclusion
Proc type type Handler = proc(params): Ret

Control Flow

Construct Syntax Notes
If if cond: ... else: ...
If (expression) let x = if cond: a else: b
Case case expr: of val: ... else: ... Exhaustive
While while cond: ...
For for x in iterable: ...
For (range) for i in 0..<n: ...
For (counted) for i, x in enumerate(arr): ...
For (pairs) for k, v in pairs(table): ...
Block block label: ... Named block
Break break label
Continue continue
Return return expr
Yield yield expr In iterators
Try try: ... except E: ... finally: ...
Defer defer: expr Run at scope exit
Discard discard expr Ignore result

Case (Match) Features

Operators

Category Operators
Arithmetic + - * / div mod ^ (xor)
Comparison == != < > <= >=
Logical and or not xor
Bitwise and or not xor shl shr asr
Set + - * (intersection) < <= (subset)
Identity is (type check) of (subtype check)
Misc .. (range) ..< $ (stringify) @ (seq prefix) & (string concat)
Address addr x
Deref p[]
Arrow => (case branch, lambda)

Operator Overloading

Any operator can be overloaded: `+`, `*`, `in`, etc. Custom operators can be defined with backtick notation.

Method Call Syntax

# Object-oriented style
echo "hello".len()
x.addr().repr()

# Uniform Function Call Syntax (UFCS)
# Any proc can be called as method:
proc greet(s: string): string = "Hello " & s
"world".greet()  # "Hello world"

Generics

proc id[T](x: T): T = x

type
  Pair[T, U] = object
    first: T
    second: U

# Concepts (type constraints)
proc sort[T: SomeOrdinal](arr: var seq[T]) = ...

proc hash[T: Hashable](x: T): int =
  # T must implement Hashable concept

Memory & GC

Category Behavior
Stack Value types (object, tuple, array)
Heap (GC) ref object, seq, string, pointer to ref
Heap (manual) ptr T via alloc/dealloc
GC Optional: --gc:arc, --gc:orc, --gc:markandsweep, --gc:boehm, --gc:none

ARC/ORC (since Nim 2.0)

Manual memory

var p = alloc(sizeof(int))
p[] = 42
dealloc(p)

Macros & Metaprogramming

import macros

macro assert(cond: untyped): untyped =
  # AST manipulation at compile time
  result = quote do:
    if not `cond`:
      echo "assertion failed: ", astToStr(`cond`)
      quit(1)

# Usage
assert(1 + 1 == 3)

# Template (simpler than macro)
template repeat(n: int, body: untyped): untyped =
  for i in 0..<n:
    body

repeat(3, echo "hello")

Compile-time features

Standard Library (selected)

Module Contents
system Built-in procs, operators, types
strutils string split, join, find, replace, strip, format, parseInt, toUpper
sequtils map, filter, fold, zip, all, any, concat, deduplicate
tables Table OrderedTable CountTable TableRef
sets HashSet OrderedSet BitSet
math sqrt, sin, cos, log, pow, random, Pi, Tau, Euler
os fileExists, dirExists, createDir, removeFile, getEnv, sleep, commandLineParams
osproc execCmd, execProcess, startProcess
net Socket, connect, send, recv, listen, accept
asyncnet / asyncdispatch Async I/O with async/await
json parseJson, %* (builder), [] access, pretty
xmltree / parsexml XML parsing and construction
parseopt Command-line option parsing
critbits Crit-bit trees
sha1 / md5 / base64 Crypto primitives
times DateTime, TimeInterval, now, format, parse
streams StringStream, FileStream, MemoryStream
logging Logger with levels and handlers
macros AST types, quoteDo, newStmtList, genSym
pegs / re PEG and Regex matching
distros --os:, --cpu: detection
endians Big-endian/little-endian conversion

Error Handling

# Exceptions (runtime)
try:
  let f = open("file.txt")
  defer: f.close()
  echo f.readAll()
except IOError as e:
  echo "IO error: ", e.msg
finally:
  echo "done"

# Result type (no exception, Nim 2.0+)
from std/result import Result, Ok, Err

func div(a, b: int): Result[int, string] =
  if b == 0:
    return Err("division by zero")
  return Ok(a div b)

# Raise exceptions
raise newException(ValueError, "invalid input")

# Option type
import std/options
let x: Option[int] = some(42)
let y: Option[int] = none(int)

Compilation

nim c file.nim             # compile with C backend
nim cpp file.nim           # compile with C++ backend
nim js file.nim            # compile to JavaScript
nim r file.nim             # compile + run
nim build                  # compile project (newer)
nimble build               # compile with Nimble package
nim check file.nim         # type-check only
nim doc file.nim           # generate documentation
nim pretty file.nim        # format code

Compilation flags

--opt:speed --opt:size --opt:none -d:release --gc:orc --gc:arc --gc:markandsweep --cc:clang --cc:gcc --mm:arc --threads:on --stackTrace:on --lineTrace:on --checks:on

Nimble Package Manager

nimble init                 # create package
nimble install <pkg>       # install dependency
nimble build                # build project
nimble test                 # run tests
nimble publish              # publish to nimble registry

nimble.cfg configures package metadata, dependencies, and build rules.

C Interop

# Declare C function
proc printf(fmt: cstring): cint {.importc, varargs.}

# Import C library
proc sqrt(x: float64): float64 {.importc: "sqrt", header: "math.h".}

# Export to C
proc myFunc(a: cint): cint {.exportc.} = a * 2

# Inline C code
{.emit: """
static int add(int a, int b) { return a + b; }
""".}

proc add(a, b: cint): cint {.importc: "add".}

# C type mappings
# int → cint, char → cchar, void → pointer
# char* → cstring, struct → object {.pure, inheritable.}
# size_t → csize, size_t → csize_t

Foreign function interface features