Learn the distinction Java engineers need early: symbols are names Clojure resolves in code, while keywords are self-evaluating labels used in data.
Symbols and keywords look similar at first because both are compact identifiers. They play different roles:
Java mental model: symbols are how you refer to code; keywords are how you label data.
| Use | Prefer | Example |
|---|---|---|
| Local names and function parameters | Symbols | user, email, subtotal |
| Function and var names | Symbols | normalize-user, str/trim |
| Java class names | Symbols | String, java.time.Instant |
| Map keys and domain attributes | Keywords | :user/id, :invoice/status |
| Enum-like states | Keywords | :active, :draft, :cancelled |
| Code treated as data | Quoted symbols | 'user/id, '(map inc xs) |
Prefer keywords for maps that represent domain data:
1{:user/id 42
2 :user/name "Ada"
3 :user/status :active}
Prefer symbols when you are talking about code: locals in let, function parameters, vars created with def or defn, and namespace-qualified references like str/join.
1(def user {:user/id 42 :user/name "Ada"})
2
3(:user/id user) ;; => 42 (keyword as a function)
4(get user :user/name) ;; => "Ada"
When you see a plain token like user in code, it’s usually a symbol being resolved. When you see :user/id, it’s a keyword value being used to label and access data.
flowchart LR
A["Token in Clojure code"] --> B{"Leading colon?"}
B -->|Yes| C["Keyword: literal data label"]
B -->|No| D{"Quoted?"}
D -->|Yes| E["Symbol data: not resolved"]
D -->|No| F["Symbol: resolved as a name"]
This distinction is small, but it unlocks a lot of Clojure reading fluency. Java engineers often look for fields, constants, enums, and imports; in Clojure, symbols and keywords cover much of that surface with less ceremony.