Operators in Clojure
Learn arithmetic, comparison, logical, and threading operators in Clojure - functions in prefix notation with practical Docker-ready examples
In most languages, operators are special syntactic forms distinct from regular function calls. In Clojure — as in all Lisps — operators are just ordinary functions called using prefix notation. +, -, =, and, and or are all functions (or macros) that you invoke the same way you invoke any other function: with the name first, inside parentheses.
This uniform model has surprising consequences. Operators are variadic by default: (+ 1 2 3 4) works just like (+ 1 2). There is no operator precedence to memorize because parentheses make evaluation order explicit. And because operators are first-class values, you can pass + or < to higher-order functions like reduce and map.
This tutorial covers arithmetic, comparison, logical, and equality operators, plus Clojure’s idiomatic threading macros (-> and ->>) which serve as functional “pipe” operators for composing transformations.
Arithmetic Operators
Clojure’s arithmetic operators are variadic functions. They accept any number of arguments and return a single result.
Create a file named arithmetic.clj:
| |
Note that (/ 10 3) returns the exact ratio 10/3, not a truncated integer or an inexact float. Clojure preserves precision unless you opt into floating-point by including a decimal.
Comparison and Equality
Comparison operators in Clojure are also variadic, and they check that the relationship holds across all arguments in sequence. This means (< 1 2 3 4) is a single call that tests strictly ascending order — there is no need to chain comparisons with and.
Create a file named comparison.clj:
| |
The distinction between = and == matters: = is value equality and is strict about types, while == is numeric equivalence that treats 1, 1.0, and 1/1 as equal.
Logical Operators
Clojure’s and, or, and not are short-circuiting. Importantly, and and or return values, not booleans — they return the actual operand that determined the result. This makes them useful for providing defaults and guarding expressions.
In Clojure’s truthiness model, only false and nil are falsy. Everything else — including 0, empty strings, and empty collections — is truthy.
Create a file named logical.clj:
| |
Threading Macros: Clojure’s Pipe Operators
Threading macros are one of Clojure’s most beloved features. They let you write data transformations as a top-to-bottom pipeline instead of deeply nested function calls. -> (thread-first) inserts each result as the first argument of the next form; ->> (thread-last) inserts it as the last argument.
Create a file named threading.clj:
| |
The fact that + and < can be passed to reduce and sort is not a special case — it works because operators are functions like any other.
Running with Docker
| |
Expected Output
Running arithmetic.clj:
Addition: 9
Subtraction: 12
Multiplication: 24
Division: 5
Ratio result: 10/3
Float division: 3.3333333333333335
Integer quotient: 3
Remainder: 1
Modulo: 2
Power 2^10: 1024.0
Absolute value: 42
Increment: 6
Decrement: 4
Min of values: 1
Max of values: 9
Running comparison.clj:
1 < 2: true
1 < 2 < 3 < 4: true
1 < 3 < 2: false
5 >= 5 >= 4: true
= integers: true
= mixed numeric: false
== numeric only: true
= collections: true
not= example: true
zero?: true
pos?: true
neg?: true
even?: true
odd?: true
Running logical.clj:
and all true: 3
and with false: false
and with nil: nil
or first truthy: 42
or all falsy: false
Hello, Ada
Hello, stranger
not true: false
not nil: true
not 0: false
safe 10/2: 5
safe 10/0: false
Running threading.clj:
Nested: HELLO WORLD!
Threaded: HELLO WORLD!
{:name Ada, :age 37, :role Engineer}
Sum of squares of evens 1-10: 220
Reduce with +: 15
Sort with <: (1 1 2 3 4 5 6 9)
Key Concepts
- Operators are functions —
+,-,<,=, and friends are ordinary functions called with prefix notation, not special syntax. - Variadic by default — Arithmetic and comparison operators accept any number of arguments:
(< 1 2 3 4)tests strict ascending order in one call, and parentheses make evaluation order explicit so there are no precedence rules to memorize. - Exact arithmetic —
(/ 10 3)returns the ratio10/3, preserving precision until you opt into floating-point. =vs==—=is strict value equality (types matter);==is numeric equivalence that compares across numeric types.- Truthiness is narrow — Only
falseandnilare falsy.0,"", and[]are all truthy. and/orreturn values — They short-circuit and return the operand that decided the result, making them useful for defaults and guards.- Threading macros (
->,->>) — Transform nested calls into top-to-bottom pipelines;->threads as first argument (object-style),->>threads as last argument (sequence-style). - Operators as first-class values — Because they are functions, you can pass
+toreduceor<tosortwithout any special wrapping.
Comments
Loading comments...
Leave a Comment