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
- Branch conditions:
of val:, of val1, val2:, of 0..10:
- Range patterns, set membership, type matching
of T(someField): — pattern matching with binding
- Exhaustiveness checked for enums
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)
--gc:arc: deterministic reference counting (no cycle collector)
--gc:orc: ARC + optional cycle collector
{.acyclic.} pragma for cycle-free types
sink parameters for move semantics
cursor annotation for borrow-like semantics
Manual memory
var p = alloc(sizeof(int))
p[] = 42
dealloc(p)
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
static[T] — force compile-time evaluation
when — compile-time conditional (like #if in C)
const — compile-time constant with full Nim semantics
macro — AST-level code transformation
template — syntax-level substitution
{.pragma.} — user-definable pragmas
compileTime — run code at compile time
import macros — AST construction/manipulation
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
{.importc.} {.exportc.} {.header.} {.link.} {.nodecl.}
{.importcpp.} for C++ interop
{.importobjc.} for Objective-C
{.importjs.} for JavaScript interop
{.packed.} for ABI-compatible struct layout
{.union.} for C unions
{.bitsize.} for bitfields