jolt/clojure-features.clj

241 lines
7.5 KiB
Clojure
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;; ============================================================
;; Comprehensive Clojure Features Demo
;; ============================================================
;; 1. Destructuring (sequential & associative)
(defn destructure-demo []
(println "\n--- Destructuring ---")
;; Sequential destructuring
(let [[a b c] [10 20 30]]
(println (str "Seq destructure: a=" a ", b=" b ", c=" c)))
;; Associative destructuring with defaults
(let [{:keys [name age city] :or {city "Unknown"}} {:name "Alice" :age 30}]
(println (str "Map destructure: name=" name ", age=" age ", city=" city)))
;; Nested destructuring
(let [{[x y] :coords} {:coords [1.0 2.5]}]
(println (str "Nested destructure: x=" x ", y=" y))))
;; 2. Atoms state management
(defn atom-demo []
(println "\n--- Atoms ---")
(def counter (atom 0))
;; swap! (function-based update)
(swap! counter inc)
(println (str "After swap! inc: " @counter))
;; reset! (set new value)
(reset! counter 100)
(println (str "After reset! to 100: " @counter))
;; compare-and-set! (CAS)
(let [old @counter]
(if (compare-and-set! counter old (+ old 5))
(println (str "CAS success: " @counter))
(println "CAS failed")))
;; Using atom with swap! and multiple updates
(swap! counter #(-> % (* 2) (+ 3)))
(println (str "After thread-first swap!: " @counter)))
;; 3. Lazy sequences infinite & transformed
(defn lazy-seq-demo []
(println "\n--- Lazy Sequences ---")
;; Infinite lazy seq: natural numbers
(def naturals (iterate inc 0))
;; Take first 10 even numbers using filter (lazy)
(def first-ten-evens (take 10 (filter even? naturals)))
(println (str "First 10 evens: " (pr-str first-ten-evens)))
;; Map and take-while (lazy)
(def squares-under-50
(take-while #(< % 50) (map #(* % %) (range))))
(println (str "Squares under 50: " (pr-str squares-under-50)))
;; Cycle and interpose (lazy)
(def repeated-pattern (take 10 (cycle [:a :b :c])))
(println (str "Cycled pattern: " (pr-str repeated-pattern)))
;; Lazy seq from recursion (not fully lazy, but demonstrates lazy cons)
(defn my-iterate [f x]
(lazy-seq (cons x (my-iterate f (f x)))))
(def powers-of-two (take 8 (my-iterate #(* 2 %) 1)))
(println (str "Powers of two: " (pr-str powers-of-two))))
;; 4. Transducers composable transformations
(defn transducer-demo []
(println "\n--- Transducers ---")
;; Compose mapping and filtering as a transducer
(def xf (comp (map inc) (filter odd?)))
;; Apply to a collection (into)
(def result (into [] xf (range 10)))
(println (str "Transducer result: " (pr-str result)))
;; Use with sequence (sequence)
(def seq-result (sequence xf (range 10)))
(println (str "Transducer seq: " (pr-str seq-result))))
;; 5. Protocols & Records polymorphism
(defprotocol Shape
(area [this])
(description [this]))
(defrecord Circle [radius]
Shape
(area [_] (* Math/PI radius radius))
(description [_] (str "Circle with radius " radius)))
(defrecord Rectangle [width height]
Shape
(area [_] (* width height))
(description [_] (str "Rectangle " width "x" height)))
(defn protocol-demo []
(println "\n--- Protocols & Records ---")
(def c (->Circle 5))
(def r (->Rectangle 3 4))
(println (str (description c) " -> area: " (area c)))
(println (str (description r) " -> area: " (area r))))
;; 6. Multimethods dispatch on arbitrary values
(defmulti shape-type :kind)
(defmethod shape-type :circle [_] "round")
(defmethod shape-type :rectangle [_] "angular")
(defmethod shape-type :default [_] "unknown")
(defn multimethod-demo []
(println "\n--- Multimethods ---")
(def s1 {:kind :circle :radius 5})
(def s2 {:kind :rectangle :width 3 :height 4})
(def s3 {:kind :triangle})
(println (str "Circle type: " (shape-type s1)))
(println (str "Rectangle type: " (shape-type s2)))
(println (str "Triangle type: " (shape-type s3))))
;; 7. Macros compile-time code generation
(defmacro log-call [expr]
`(let [result# ~expr]
(println (str "Called: " (pr-str '~expr) " -> " result#))
result#))
(defn macro-demo []
(println "\n--- Macros ---")
(log-call (* 2 3))
(log-call (map inc [1 2 3]))
(log-call (reduce + (range 1 6))))
;; 8. Recursion linear and tail-recursive
(defn recursion-demo []
(println "\n--- Recursion ---")
;; Linear recursion: factorial
(defn fact [n]
(if (<= n 1) 1 (* n (fact (dec n)))))
(println (str "Factorial 5: " (fact 5)))
;; Tail recursion with recur
(defn fact-tail [n]
(loop [i n acc 1]
(if (zero? i) acc
(recur (dec i) (* acc i)))))
(println (str "Tail-factorial 5: " (fact-tail 5)))
;; Mutual recursion with trampoline
(declare even?)
(defn odd? [n]
(if (zero? n) false (even? (dec n))))
(defn even? [n]
(if (zero? n) true (odd? (dec n))))
(println (str "Is 6 even? " (even? 6))))
;; 9. Higher-order functions partial, comp, juxt
(defn hof-demo []
(println "\n--- Higher-Order Functions ---")
(def add5 (partial + 5))
(println (str "Partial (+5) applied to 10: " (add5 10)))
(def inc-and-double (comp #(* 2 %) inc))
(println (str "Comp (double∘inc) on 3: " (inc-and-double 3)))
(def stats (juxt identity inc dec))
(println (str "Juxt on 5: " (stats 5))))
;; 10. Threading macros (-> and ->>)
(defn threading-demo []
(println "\n--- Threading Macros ---")
(def result
(->> (range 20)
(filter odd?)
(map #(* % 3))
(take 5)
(reduce +)))
(println (str "Threaded pipeline result: " result))
(def threaded-sqrt
(-> 25 Math/sqrt long (+ 10)))
(println (str "Thread-first sqrt: " threaded-sqrt)))
;; 11. Exception handling with try/catch/finally
(defn exception-demo []
(println "\n--- Exception Handling ---")
(try
(throw (ex-info "something broke" {:code 42}))
(catch :default e
(println (str "Caught: " (ex-message e) " " (pr-str (ex-data e)))))
(finally
(println "Finally block executed."))))
;; 12. Clojure's sequence comprehension: for (list comprehension)
(defn for-demo []
(println "\n--- For Comprehension ---")
(def combos
(for [x (range 3)
y (range 3)
:when (not= x y)]
[x y]))
(println (str "Combinations (x!=y): " (pr-str combos))))
;; 13. Clojure's core.async? Not pure Clojure, skip.
;; 14. Janet host interop — Jolt runs on Janet, so host interop is Janet-style:
;; `.` dispatches on a table/struct (the receiver is passed as the first
;; arg), and Janet's standard library is reachable through jolt.interop.
(defn janet-interop-demo []
(println "\n--- Janet Interop ---")
;; Method-style call on a Janet table: self is passed as the first argument.
(def counter {:value 41
:describe (fn [self] (str "counter = " (:value self)))})
(println (str "Method call: " (. counter describe)))
;; Field access sugar: (.-k m) is (. m :k)
(println (str "Field access: " (.-value counter)))
;; Reach Janet's standard library through jolt.interop.
(require '[jolt.interop :as j])
(println (str "Janet type: " (j/janet-type [1 2 3])))
(println (str "Table keys: " (pr-str (j/janet-table-keys {:a 1 :b 2})))))
;; ---------- Main entry point ----------
(defn -main []
(println "=== Clojure Features Demo ===")
(destructure-demo)
(atom-demo)
(lazy-seq-demo)
(transducer-demo)
(protocol-demo)
(multimethod-demo)
(macro-demo)
(recursion-demo)
(hof-demo)
(threading-demo)
(exception-demo)
(for-demo)
(janet-interop-demo)
(println "\n=== Demo Complete ==="))
;; Run if executed as script
(-main)