| name | swe-programming-clojure |
| description | Clojure coding standards from authoritative docs/explanation/software-engineering/programming-languages/clojure/ documentation |
Clojure Coding Standards
Purpose
Progressive disclosure of Clojure coding standards for agents writing Clojure code.
Usage: Auto-loaded for agents when writing Clojure code. Provides quick reference to idioms, best practices, and antipatterns.
Authoritative Source: docs/explanation/software-engineering/programming-languages/clojure/README.md
Prerequisite Knowledge
IMPORTANT: This skill provides demo-specific style guides, not educational tutorials.
Complete the demo Clojure learning path first:
Quick Standards Reference
Naming Conventions
Functions/Variables: kebab-case - calculate-zakat, total-amount, validate-contract
Predicates: end with ? - valid-nisab?, above-threshold?
Side-effecting functions: end with ! - save-transaction!, send-notification!
Namespaces: reverse-domain + feature - com.demo.zakat.calculator
Namespace aliases: standard abbreviations - (require [clojure.string :as str])
Core Idioms
;; CORRECT: Pure function for Zakat calculation
(defn calculate-zakat
"Calculate Zakat amount. Returns 2.5% if wealth >= nisab, else 0."
[wealth nisab]
(if (>= wealth nisab)
(* wealth 0.025M)
0M))
;; CORRECT: Threading macro for readability
(defn process-contracts [contracts nisab]
(->> contracts
(filter #(>= (:wealth %) nisab))
(map #(assoc % :zakat-amount (calculate-zakat (:wealth %) nisab)))
(remove nil?)))
;; CORRECT: Destructuring in function args
(defn format-payment [{:keys [amount currency date]}]
(str amount " " currency " on " date))
Namespaced Keywords for Domain
;; CORRECT: Namespaced keywords for domain concepts
{:zakat/wealth 10000M
:zakat/nisab 5000M
:zakat/amount 250M
:contract/id "murabaha-001"
:contract/type :murabaha
:contract/status :active}
;; WRONG: Unnamespaced keywords for domain data
{:wealth 10000M ; ambiguous in a larger system
:id "001"}
Error Handling
;; CORRECT: ex-info for structured errors
(defn validate-wealth [wealth]
(when (neg? wealth)
(throw (ex-info "Invalid wealth amount"
{:type :validation-error
:field :wealth
:value wealth
:message "Wealth cannot be negative"}))))
;; CORRECT: Catch specific ex-info
(try
(validate-wealth -100M)
(catch clojure.lang.ExceptionInfo e
(let [data (ex-data e)]
(log/error "Validation failed" data))))
Concurrency with Atoms
;; CORRECT: Atom for uncoordinated state
(def zakat-cache (atom {}))
;; CORRECT: swap! for atomic update (pure function)
(defn cache-calculation! [wealth result]
(swap! zakat-cache assoc wealth result))
;; CORRECT: Refs for coordinated STM
(def total-zakat (ref 0M))
(def transaction-log (ref []))
(defn record-zakat! [amount]
(dosync
(alter total-zakat + amount)
(alter transaction-log conj {:amount amount :time (java.time.Instant/now)})))
Transducers for Efficiency
;; CORRECT: Transducer pipeline (lazy, composable)
(def eligible-contracts-xf
(comp
(filter #(>= (:wealth %) nisab-threshold))
(map #(assoc % :zakat (* (:wealth %) 0.025M)))
(take 100)))
;; Apply to any collection
(into [] eligible-contracts-xf all-contracts)
(transduce eligible-contracts-xf + all-contracts)
Testing
;; CORRECT: clojure.test with descriptive names
(ns com.demo.zakat.calculator-test
(:require [clojure.test :refer [deftest testing is are]]
[com.demo.zakat.calculator :refer [calculate-zakat]]))
(deftest calculate-zakat-test
(testing "wealth above nisab"
(is (= 250M (calculate-zakat 10000M 5000M))))
(testing "wealth below nisab"
(is (= 0M (calculate-zakat 1000M 5000M))))
(testing "wealth equal to nisab"
(is (= 125M (calculate-zakat 5000M 5000M)))))
Comprehensive Documentation
Authoritative Index: docs/explanation/software-engineering/programming-languages/clojure/README.md
Mandatory Standards
- Coding Standards
- Testing Standards
- Code Quality Standards
- Build Configuration
Context-Specific Standards
- Error Handling
- Concurrency
- Functional Programming
- Performance
- Security
- API Standards
- DDD Standards
- Java Interop
Related Skills
- docs-applying-content-quality
- repo-practicing-trunk-based-development
References