Operators in Crystal
Master arithmetic, comparison, logical, bitwise, and range operators in Crystal with type-aware examples and Docker-ready code
Operators are the verbs of a programming language - they tell the compiler how to combine, compare, and transform values. In Crystal, operators look familiar to anyone who has used Ruby, but they carry static-type semantics under the hood. Every operator is actually a method call, which means you can overload them on your own types just like in Ruby, while the LLVM-based compiler still produces efficient native machine code.
Because Crystal is statically typed with inference, the compiler resolves which method an operator dispatches to at compile time. This produces clear errors when you mix incompatible types, and it makes operator overloading a first-class tool rather than a runtime cost. In this tutorial you will see arithmetic, comparison, logical, bitwise, assignment, and range operators, plus a glimpse at how Crystal treats operators as methods.
You will also encounter operator precedence, the <=> “spaceship” operator used by Comparable, and Crystal’s strict approach to mixing numeric types.
Arithmetic Operators
Crystal supports the standard arithmetic operators along with integer division and exponentiation. Integer division (//) always rounds toward negative infinity, while / between two integers produces a Float64.
Create a file named operators_arithmetic.cr:
| |
Notice that 17 / 5 produces a Float64, while 17 // 5 stays in the integer domain - a deliberate design choice that distinguishes mathematical division from integer truncation.
Comparison and the Spaceship Operator
Comparison operators return Bool. The <=> operator returns -1, 0, or 1 (an Int32) and is the foundation of the Comparable module.
Create a file named operators_comparison.cr:
| |
Logical and Bitwise Operators
Crystal uses &&, ||, and ! for short-circuit boolean logic. Only nil and false are falsy - every other value, including 0 and "", is truthy. The &, |, ^, ~, <<, and >> operators work bitwise on integers.
Create a file named operators_logical.cr:
| |
Assignment, Ranges, and Operators as Methods
Compound assignment (+=, -=, etc.) is shorthand for x = x + y. Crystal also has the special ||= and &&= forms for conditional assignment - very useful when working with nilable values. Ranges (.. and ...) build Range objects that play well with iteration and collections.
Most operators are actually methods, so you can define them on your own types. Below we overload + on a small Vector struct.
Create a file named operators_advanced.cr:
| |
Running with Docker
| |
Expected Output
operators_arithmetic.cr:
a + b = 22
a - b = 12
a * b = 85
a / b = 3.4
a // b = 3
a % b = 2
a ** b = 1419857
-a = -17
operators_comparison.cr:
x == y : false
x != y : true
x < y : true
x <= y : true
x > y : false
x >= y : false
x <=> y: -1
"apple" <=> "banana": -1
s1 == s2 : true
s1.same?(s2): false
operators_logical.cr:
t && f : false
t || f : true
!t : false
display = anonymous
0 is truthy : true
"" is truthy: true
0b1100 & 0b1010 = 1000
0b1100 | 0b1010 = 1110
0b1100 ^ 0b1010 = 0110
1 << 4 = 16
32 >> 2 = 8
operators_advanced.cr:
score = 30
greeting = Hello
inclusive sum = 15
exclusive to_a = [1, 2, 3, 4]
v = (4, 6)
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
Key Concepts
- Operators are methods -
a + bis sugar fora.+(b), which is why you can overload operators on your own types. /vs//- Integer/produces aFloat64;//performs floor division and stays in the integer domain.- Strict truthiness - Only
nilandfalseare falsy in Crystal;0,"", and empty collections are all truthy. - Short-circuit results -
||and&&return one of their operands, not a coercedBool, which makes idioms likevalue ||= defaultnatural. <=>powersComparable- Implementing the spaceship operator on a type, plusinclude Comparable, automatically gives you<,<=,>,>=, andbetween?.- Compile-time type checking - Crystal rejects nonsense like
1 + "x"at compile time rather than failing at runtime. - Ranges are first-class -
..(inclusive) and...(exclusive) produceRangeobjects that integrate with iteration, slicing, and pattern matching. - Precedence follows convention - Multiplicative operators bind tighter than additive ones; use parentheses whenever clarity is in doubt.
Running Today
All examples can be run using Docker:
docker pull crystallang/crystal:1.14.0
Comments
Loading comments...
Leave a Comment