Build functions from functions with comp/partial/juxt plus apply and memoize for practical pipelines.
These functions let you assemble small, testable pieces into bigger behavior—without creating “utility classes” or deep inheritance trees.
comp (Compose Functions, Right-to-Left)comp returns a new function. The rightmost function runs first.
1(require '[clojure.string :as str])
2
3(def normalize-id
4 (comp keyword str/lower-case str/trim))
5
6(normalize-id " User/Admin ")
7;; => :user/admin
If you prefer left-to-right reading in pipelines, you’ll often use threading macros (->, ->>) instead of deep comp.
partial (Pre-Fill Arguments)1(def add10 (partial + 10))
2
3(add10 5) ; => 15
4(map (partial * 2) [1 2 3]) ; => (2 4 6)
juxt (Run Many Functions on the Same Input)juxt returns a function that returns a vector of results.
1((juxt count first last) [10 20 30])
2;; => [3 10 30]
apply (Spread a Collection Into Arguments)1(apply max [3 10 7]) ; => 10
memoize (Cache Results of a Pure Function)1(def slow-f (memoize (fn [x] (Thread/sleep 50) (* x x))))
2
3(slow-f 10) ; first call: slow
4(slow-f 10) ; second call: fast (cached)
Use memoize only when the function is pure and the cache won’t grow without bound (or you’re okay with that trade-off).