Overview of Clojure Features
A Java-oriented tour of the features that shape idiomatic Clojure: persistent data, first-class functions, macros, and concurrency.
Clojure’s “feature list” is not just trivia—it changes how you structure programs. This section focuses on the features that most affect everyday engineering work for Java developers: how you represent data, how you compose behavior, and how you handle state and concurrency.
The goal is not to memorize keywords. It is to build accurate mental models you can use in code review:
- persistent collections and structural sharing
- functions as values (higher-order programming)
- macros as a compile-time tool (used sparingly)
- concurrency tools built around immutable values plus explicit references
Knowledge Check: Clojure’s Core Features
### What does it mean that Clojure collections are “persistent”?
- [x] Updates return a new value and reuse structure from the old value instead of mutating it in place.
- [ ] Collections automatically persist to disk on every update.
- [ ] Values cannot be garbage-collected.
- [ ] Maps can only use keywords as keys.
> **Explanation:** Persistent data structures are immutable. “Persistent” here refers to structural sharing across versions, not persistence to storage.
### What does “functions are first-class” allow you to do?
- [x] Pass functions as arguments, return them, and store them in data structures.
- [ ] Use functions only at the top level of a file.
- [ ] Define functions without namespaces.
- [ ] Avoid using collections.
> **Explanation:** Treating functions as values is what makes higher-order patterns like `map`, `reduce`, and function composition feel natural.
### What’s the most important difference between a macro and a function?
- [x] A macro transforms code forms before evaluation; a function evaluates its arguments and operates on values.
- [ ] A macro is always faster than a function.
- [ ] A macro can only be used for concurrency.
- [ ] A macro cannot call other functions.
> **Explanation:** Macros operate on the unevaluated structure of code. Prefer functions first; reach for macros when you truly need a new syntactic shape or control structure.
In this section