Beginner

Operators in Nim

Learn arithmetic, comparison, logical, and bitwise operators in Nim, plus how to define your own custom operators.

Operators are the building blocks of expressions. In Nim, operators behave much like they do in Python or C, but with a few twists rooted in Nim’s static, strongly-typed nature. Because Nim is statically typed with type inference, the compiler decides which version of an operator to call based on the types of its operands — and you can define entirely new operators yourself.

Nim is a multi-paradigm language (procedural, object-oriented, functional, metaprogramming), so operators are not magic syntax: they are just procedures with symbolic names. This means 1 + 2 is sugar for `+`(1, 2), and you can overload or invent operators using the same proc keyword used for any other function.

In this tutorial you’ll see arithmetic, comparison, logical, bitwise, and assignment operators, learn how Nim handles integer vs. floating-point division, and finish by defining a custom operator.

Arithmetic, Division, and Modulo

Nim uses familiar infix arithmetic operators: +, -, *, /, plus div and mod for integer division and remainder. Note the important distinction: / always returns a float, while div performs integer division.

Create a file named arithmetic.nim:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
let a = 17
let b = 5

echo "a + b = ", a + b
echo "a - b = ", a - b
echo "a * b = ", a * b
echo "a / b = ", a / b      # float division
echo "a div b = ", a div b  # integer division
echo "a mod b = ", a mod b  # remainder

# Power operator from the math module
from std/math import `^`
echo "2 ^ 10 = ", 2 ^ 10

# Unary minus
let n = -42
echo "negated = ", -n

The ^ integer power operator lives in the std/math module and must be imported. Floating-point exponentiation uses pow from the same module.

Comparison and Logical Operators

Comparisons in Nim return a bool. The logical operators and, or, not, and xor are spelled as words (not && / ||) and short-circuit where appropriate.

Create a file named comparison.nim:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
let x = 10
let y = 20

echo "x == y: ", x == y
echo "x != y: ", x != y
echo "x <  y: ", x < y
echo "x <= y: ", x <= y
echo "x >  y: ", x > y
echo "x >= y: ", x >= y

# Chained logical operators
let inRange = x > 0 and x < 100
let outside = x < 0 or x > 100
echo "inRange: ", inRange
echo "outside: ", outside
echo "not inRange: ", not inRange
echo "true xor false: ", true xor false

Bitwise and Shift Operators

Because Nim targets systems programming, it offers a full set of bitwise operators. They are spelled with words to avoid confusion with logical operators: and, or, xor, not, shl, shr. The compiler picks the bitwise meaning when both operands are integers.

Create a file named bitwise.nim:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import std/strutils

let flags = 0b1010
let mask  = 0b1100

echo "flags and mask = 0b", toBin(flags and mask, 4)
echo "flags or  mask = 0b", toBin(flags or mask, 4)
echo "flags xor mask = 0b", toBin(flags xor mask, 4)
echo "not flags (8-bit) = 0b", toBin(not flags and 0xFF, 8)
echo "flags shl 2   = ", flags shl 2
echo "flags shr 1   = ", flags shr 1

Note: toBin lives in std/strutils and must be imported explicitly. It formats an integer as a binary string padded to the given width.

Assignment, Compound, and String Operators

Nim supports compound assignment (+=, -=, *=, /=) on mutable var bindings. Strings concatenate with &, and &= appends in place.

Create a file named assignment.nim:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var counter = 0
counter += 5
counter -= 2
counter *= 3
echo "counter = ", counter   # (0+5-2)*3 = 9

# String concatenation with &
let greeting = "Hello" & ", " & "Nim"
echo greeting

# In-place string append
var message = "Count: "
message &= $counter          # $ converts int to string
echo message

The $ prefix is Nim’s stringify operator — it converts any value with a defined $ proc to a string. It’s the operator behind echo.

Operator Precedence and Custom Operators

Nim’s precedence rules mostly mirror mathematics: unary operators bind tightest, then *, /, div, mod, then + and -, then comparisons, then and, then or. Use parentheses when in doubt.

Because operators are just procedures, you can define your own. Symbolic identifiers must be wrapped in backticks at the definition site.

Create a file named custom_op.nim:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Define a custom '**' operator for integer power
proc `**`(base, exp: int): int =
  result = 1
  for _ in 1 .. exp:
    result *= base

echo "2 ** 8  = ", 2 ** 8
echo "3 ** 4  = ", 3 ** 4

# Precedence demo: * binds tighter than +
echo "2 + 3 * 4   = ", 2 + 3 * 4    # 14, not 20
echo "(2 + 3) * 4 = ", (2 + 3) * 4  # 20

The name of a custom operator determines its precedence: operators ending in = (other than ==, <=, etc.) get the lowest precedence, and the first character of the operator name signals its precedence class (see the Nim manual for the full table).

Running with Docker

1
2
3
4
5
6
7
8
9
# Pull the official Nim image
docker pull nimlang/nim:alpine

# Compile and run each example
docker run --rm -v $(pwd):/app -w /app nimlang/nim:alpine nim c -r arithmetic.nim
docker run --rm -v $(pwd):/app -w /app nimlang/nim:alpine nim c -r comparison.nim
docker run --rm -v $(pwd):/app -w /app nimlang/nim:alpine nim c -r bitwise.nim
docker run --rm -v $(pwd):/app -w /app nimlang/nim:alpine nim c -r assignment.nim
docker run --rm -v $(pwd):/app -w /app nimlang/nim:alpine nim c -r custom_op.nim

Expected Output

Output from arithmetic.nim:

a + b = 22
a - b = 12
a * b = 85
a / b = 3.4
a div b = 3
a mod b = 2
2 ^ 10 = 1024
negated = 42

Output from comparison.nim:

x == y: false
x != y: true
x <  y: true
x <= y: true
x >  y: false
x >= y: false
inRange: true
outside: false
not inRange: false
true xor false: true

Output from bitwise.nim:

flags and mask = 0b1000
flags or  mask = 0b1110
flags xor mask = 0b0110
not flags (8-bit) = 0b11110101
flags shl 2   = 40
flags shr 1   = 5

Output from assignment.nim:

counter = 9
Hello, Nim
Count: 9

Output from custom_op.nim:

2 ** 8  = 256
3 ** 4  = 81
2 + 3 * 4   = 14
(2 + 3) * 4 = 20

Key Concepts

  • Operators are procedures. a + b is shorthand for `+`(a, b), which means any operator can be overloaded or newly defined with proc.
  • / vs div. The / operator always yields a float; use div for integer division and mod for the remainder.
  • Word-spelled logical and bitwise operators. and, or, xor, not, shl, shr serve both logical and bitwise duty — the compiler chooses based on operand types.
  • String concatenation uses &. Use $ to stringify any value before concatenating.
  • Compound assignment requires var. let bindings are immutable, so += and friends only apply to var.
  • Custom operators inherit precedence from their first character. This lets you design DSL-like syntax without surprising the parser.
  • Power lives in std/math. Import ^ (integer) or pow (float) when you need exponentiation.

Running Today

All examples can be run using Docker:

docker pull nimlang/nim:alpine
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining