From d9fbc9bdb63cbf058fdf4a8eca33e74e53206c71 Mon Sep 17 00:00:00 2001 From: ajet Date: Mon, 14 Sep 2026 07:26:40 -0900 Subject: [PATCH] add clj examples --- learnclj.clj | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 learnclj.clj diff --git a/learnclj.clj b/learnclj.clj new file mode 100644 index 0000000..88a4447 --- /dev/null +++ b/learnclj.clj @@ -0,0 +1,334 @@ +;; ============================================ +;; learnclj.clj — Clojure Learning Examples +;; ============================================ +(ns learnclj + (:require [clojure.string :as str])) + +;; --- 1. Basics --- + +;; Literals +123 ; => 123 (Integer) +3.14 ; => 3.14 (Double) +22/7 ; => 22/7 (Ratio/rational) +:keyword ; => :keyword (Keyword) +"string" ; => "string" (String) +\c ; => \c (Character) +true ; => true (Boolean) +nil ; => nil (Null/Nothing) + +;; --- 2. Defining Values & Functions --- + +;; def — binds a name to a value in the namespace +(def π 3.14159265) + +;; defn — defines a function +(defn greet [name] + (str "Hello, " name "!")) +(greet "Sam") ;; => "Hello, Sam!" + +;; Anonymous function +(#(+ %1 %2) 3 4) ; => 7 +(fn [x y] (+ x y)) ; => #object[clojure.core$fn__... 0x... "fn..."] (anonymous function) + +;; Function with default arguments +(defn greet-default [name {:keys [formal] :or {formal false}}] + (if formal + (str "Good day, " name) + (str "Hey, " name))) +(greet-default "Sam" {}) ; => "Hey, Sam" +(greet-default "Sam" {:formal true}) ; => "Good day, Sam" + +;; Variadic function +(defn sum [& numbers] + (reduce + 0 numbers)) +(sum 1 2 3 4) ; => 10 + +;; --- 3. Data Structures --- + +;; Lists — linked lists, quoted for data +'(1 2 3) ; => (1 2 3) (quoted list) +(list 1 2 3) ; => (1 2 3) + +;; Vectors — indexed, sequential +[1 2 3] ; => [1 2 3] +(vector "a" "b" "c") ; => ["a" "b" "c"] +(get [10 20 30] 1) ; => 20 + +;; Maps — key-value pairs +{:name "Alice" :age 30} ; => {:name "Alice", :age 30} +{"x" 1 "y" 2} ; => {"x" 1, "y" 2} +(get {:a 1 :b 2} :a) ; => 1 +(:name {:name "Alice"}) ; => "Alice" (keyword as accessor) + +;; Sets — unique values +#{1 2 3 4 5} ; => #{1 2 3 4 5} (order not guaranteed) +(set [1 2 2 3 3 3]) ; => #{1 2 3} (duplicates removed, order not guaranteed) + +;; --- 4. Control Flow --- + +;; if +(if (> 5 3) + "yes" + "no") ; => "yes" + +;; when — like if but for side effects (no else branch) +(when true + (print "Side effect here") + :result) ; => :result + +;; cond — multiple conditions +(cond + (= 1 1) "one" + (= 2 2) "two" + :else "other") ; => "one" + +;; case — exact match dispatch +(case 2 + 1 "one" + 2 "two" + 3 "three" + "other") ; => "two" + +;; and / or — short-circuiting +(and true false nil) ; => false (returns first falsy value) +(or false true 42) ; => true + +;; --- 5. Sequences --- + +;; map — apply function to each element +(map inc [1 2 3]) ; => (2 3 4) +(map str ["a" "b"] [1 2]) ; => ("a1" "b2") + +;; filter +(filter even? [1 2 3 4 5]) ; => (2 4) + +;; reduce +(reduce + [1 2 3 4]) ; => 10 +(reduce str ["a" "b" "c"]) ; => "abc" + +;; into — combine collections +(into [] (map inc [1 2 3])) ; => [2 3 4] +(into {} (map #(vector %1 %2) [:a :b] [1 2])) ; => {:a 1, :b 2} + +;; sequence processing +(sequence (comp + (filter odd?) + (map #(* % %))) + [1 2 3 4 5 6 7]) ; => (1 9 25 49) + +;; --- 6. Destructuring --- + +;; Vector destructuring +(let [[first second & rest] [1 2 3 4 5]] + [first second rest]) +; => [1 2 (3 4 5)] + +;; Map destructuring +(let [{name :name age :age} {:name "Bob" :age 25}] + [name age]) +; => ["Bob" 25] + +;; Nested destructuring +(let [{:keys [x y] :as point} {:point {:x 10 :y 20}} + {:keys [x y]} (:point point)] + [x y]) +; => [10 20] + +;; Function parameter destructuring +(defn show-point [{:keys [x y] :or {x 0 y 0}}] + (str "Point: (" x ", " y ")")) +(show-point {:x 10 :y 20}) ; => "Point: (10, 20)" +(show-point {}) ; => "Point: (0, 0)" + +;; --- 7. Namespaces --- + +;; require — load a namespace +;; (require '[clojure.string :as str]) +;; (str/upper-case "hello") + +;; use — import functions directly +;; (use '[clojure.string :only [upper-case]]) +;; (upper-case "hello") + +;; import — Java classes +;; (import java.util.Date) +;; (Date.) + +;; --- 8. Recursion & Tail Recursion --- + +;; Regular recursion +(defn factorial [n] + (if (<= n 1) + 1 + (* n (factorial (dec n))))) + +;; Tail-recursive with loop/recur +(defn factorial-tail [n] + (loop [n n acc 1] + (if (<= n 1) + acc + (recur (dec n) (* acc n))))) + +;; --- 9. Conditionals with when-let / if-let --- + +;; when-let — bind and condition in one +(when-let [val (get {:a 1} :b)] + val) ; => nil (doesn't evaluate body) + +(if-let [val (get {:a 1} :a)] + val + "not found") ; => 1 + +;; --- 10. Multiline strings & syntax quoting --- + +;; Multiline string +(def multiline + "This is a + multiline + string") + +;; Syntax quoting (backquote) — auto-qualifies vars +(defn make-list [] + `(~"a" ~"b" "c")) ; => ("a" "b" "c") + +;; --- 11. Protocols (OOP-like) --- + +(defprotocol Shape + (area [this]) + (perimeter [this])) + +(deftype Rectangle [width height] + Shape + (area [this] (* width height)) + (perimeter [this] (* 2 (+ width height)))) + +(defn make-rectangle [w h] + (Rectangle. w h)) + +(make-rectangle 4 5) ; => #object[learnclj.Rectangle ...] +(area (make-rectangle 4 5)) ; => 20 +(perimeter (make-rectangle 4 5)) ; => 18 + +;; --- 12. Records --- + +(defrecord Person [name age email]) + +(def alice (->Person "Alice" 30 "alice@example.com")) +(:name alice) ; => "Alice" +(->Person "Alice" 30 "alice@example.com") ; => #learnclj.Person{:name "Alice", :age 30, :email "alice@example.com"} +(map->Person {:name "Bob" :age 25 :email "bob@example.com"}) ; => #learnclj.Person{:name "Bob", :age 25, :email "bob@example.com"} + +;; --- 12b. Type & Protocol Extension --- + +;; Protocol to define +(defprotocol Formattable + (format-for-display [this] "Returns a formatted string representation")) + +;; extend-type — add protocol methods to an existing type +(extend-type Number + Formattable + (format-for-display [this] + (if (integer? this) + (str "Int: " this) + (str "Num: " this)))) + +(format-for-display 42) ; => "Int: 42" +(format-for-display 3.14) ; => "Num: 3.14" + +;; extend-protocol — add protocol methods to multiple types at once +(extend-protocol Formattable + java.util.Date + (format-for-display [this] + (str "[Date] " (.toString this))) + + java.util.Calendar + (format-for-display [this] + (str "[Calendar] " (.getTime this))) + + java.util.UUID + (format-for-display [this] + (str "[UUID] " (.toString this)))) + +(format-for-display (java.util.Date.)) ; => "[Date] ..." +(format-for-display (java.util.UUID/randomUUID)) ; => "[UUID] ..." + +;; --- 13. Atoms & State --- + +(def counter (atom 0)) + +(swap! counter inc) ; => 1 +(swap! counter + 5) ; => 6 +(dosync + (reset! counter 0)) ; => 0 + +;; --- 14. Java Interop --- + +;; Method call +(.toUpperCase "hello") ; => "HELLO" +(.substring "hello" 1 3) ; => "el" +(. "hello" length) ; => 5 +(.length "hello") ; => 5 +(.age alice) ; => 30 +(.. alice email toUpperCase) ; => "ALICE@EXAMPLE.COM" + +;; Static method +(System/getProperty "user.name") ; => "ajet" + +;; Constructor +(java.util.Date.) ; => #inst "2026-09-14T..." (current date/time) + +;; --- 15. Threading Macros --- + +;; Thread-first (->) — passes result as first arg +(-> "hello" + (.toUpperCase) + (.replace "H" "J") + (.toLowerCase)) ; => "jello" + +;; Thread-last (->>) — passes result as last arg +(->> [1 2 3 4 5] + (filter odd?) + (map #(* % %)) + (reduce +)) ; => 35 + +;; --- 16. Error Handling --- + +;; try/catch +(try + (/ 1 0) + (catch ArithmeticException e + (str "Math error: " (.getMessage e)))) ; => "Math error: Divide by zero" + +;; assert — throws AssertionError on failure +(assert (= 2 (+ 1 1))) ; => nil (assert returns nil on success) +;; (assert (= 1 2) "custom message") ; would throw with custom message + +;; --- 17. Macros (simplified) --- + +;; Define a simple macro +(defmacro unless [pred & body] + `(if (not ~pred) + ~@body)) + +(unless true + (print "Won't print") + "result") ; => "result" + +;; --- 18. Common Patterns --- + +;; Compose functions +(defn make-upper [s] (str/upper-case s)) +(def make-upper-lower (comp str/lower-case str/upper-case)) ; => #object[clojure.core$comp$fn ...] + +;; Partial application + +;; Partial application +(def add-5 (partial + 5)) +(add-5 3) ; => 8 + +;; Complement — negate a predicate +(every-pred (complement nil?) (complement zero?)) ; => #object[clojure.core$every_pred ...] + +;; Juxt — create multiple functions +(def j (juxt :x :y)) ; => #object[clojure.core$juxt ...] +(j {:x 1 :y 2}) ; => [1 2]