Variables and Types in Nim
Learn about variables, data types, and type conversions in Nim with practical Docker-ready examples
Nim’s type system is one of its defining features — statically typed and strongly checked at compile time, yet remarkably ergonomic thanks to powerful type inference. Where languages like Python give you freedom at the cost of runtime surprises, and languages like Java demand verbose declarations, Nim strikes a balance: the compiler catches type errors before your code ever runs, but you rarely need to spell out types explicitly.
Understanding Nim’s variable system starts with three keywords: var, let, and const. Each gives you a different level of mutability, and choosing the right one signals intent to both the compiler and anyone reading your code. Combined with Nim’s rich set of built-in types, distinct types for domain safety, and seamless type conversions, you’ll find a type system that’s both practical and expressive.
In this tutorial, you’ll learn how to declare variables with different mutability levels, work with Nim’s primitive and compound types, convert between types safely, and use distinct types to prevent logical errors at compile time.
Variable Declarations: var, let, and const
Nim provides three ways to bind a name to a value, each with different guarantees about mutability.
Create a file named variables.nim:
| |
This first example covers the fundamentals: the three declaration keywords, type inference, and all of Nim’s primitive types. Note that let and const both create immutable values, but const is evaluated at compile time — it must be computable without running the program. Use let for values determined at runtime and const for true constants.
Type Conversions and Distinct Types
Nim does not perform implicit conversions between types. You must be explicit, which prevents subtle bugs common in languages with automatic coercion.
Create a file named variables_types.nim:
| |
Nim’s distinct types are particularly powerful — they create new types that are incompatible with their base type, catching unit mismatch errors at compile time rather than at runtime. The $ operator is Nim’s universal “convert to string” convention, and you can define it for your own types.
Running with Docker
| |
Expected Output
Output from variables.nim:
count = 10
name = Nim Language
language = Nim
version = 2.0
Pi = 3.14159265
MaxSize = 1024
Greeting = Hello from Nim
wholeNumber = 42
decimal = 3.14
flag = true
letter = A
text = Hello
small (int8) = 127
medium (int16) = 32000
large (int64) = 9000000000
positive (uint) = 42
single (float32) = 1.5
double (float64) = 1.123456789012345
Output from variables_types.nim:
int to float: 42 -> 42.0
float to int (truncates): 3.99 -> 3
int to string: 256
float to string: 3.14159
bool to string: true
string to int: 100
string to float: 2.718
distance = 500.0m
road = 3.5km
heading = North
color: red
color: green
color: blue
point = (10, 20)
numbers = @[1, 2, 3, 4, 5, 6]
length = 6
grid = ["alpha", "beta", "gamma"]
grid[0] = alpha
Key Concepts
- Three mutability levels —
varfor mutable variables,letfor runtime immutable bindings,constfor compile-time constants. Preferletandconstovervarwhen possible. - Type inference — Nim infers types from assigned values, so
let x = 42is the same aslet x: int = 42. Explicit annotations are optional but useful for documentation. - No implicit conversions — Nim requires explicit type conversions like
float(intVal)orint(floatVal), preventing silent data loss from automatic coercion. - The
$operator — Nim’s universal “to string” conversion. Works on all built-in types, and you can define it for your own types. - Distinct types — Create new types incompatible with their base type using
distinct, catching unit and domain errors at compile time. - Sized numeric types — Beyond
intandfloat, Nim offersint8,int16,int32,int64,uint,float32, andfloat64for precise control over memory layout. - Sequences vs arrays —
seq[T]is a growable, heap-allocated list;array[N, T]is a fixed-size, stack-allocated collection. Use arrays when the size is known at compile time. - Enumerations —
enumtypes define a set of named values, with optional string representations, and are iterable withfor.
Running Today
All examples can be run using Docker:
docker pull nimlang/nim:alpine
Comments
Loading comments...
Leave a Comment