migration
This commit is contained in:
86
clojure/examples/0_1_magic.clj
Normal file
86
clojure/examples/0_1_magic.clj
Normal file
@@ -0,0 +1,86 @@
|
||||
(defn lecture [name]
|
||||
(println)
|
||||
(let [line (clojure.string/join (repeat (+ 16 (count name)) "="))]
|
||||
(println line)
|
||||
(println "=== Lecture" name "===")
|
||||
(println line)))
|
||||
|
||||
(defn chapter [name]
|
||||
(println)
|
||||
(println "==========" name "=========="))
|
||||
|
||||
(defn section [name]
|
||||
(println)
|
||||
(println "---" name "---"))
|
||||
|
||||
|
||||
(defn- safe-eval [expression]
|
||||
(try
|
||||
(eval expression)
|
||||
(catch Throwable e e)))
|
||||
|
||||
(defmacro with-out-str-and-value [body]
|
||||
`(let [s# (new java.io.StringWriter)]
|
||||
(binding [*out* s#]
|
||||
(let [v# (safe-eval ~body)]
|
||||
(vector (str s#) v#)))))
|
||||
|
||||
(defn- init [seq]
|
||||
(take (dec (count seq)) seq))
|
||||
|
||||
(defn- prepend [prefix]
|
||||
(partial str prefix))
|
||||
|
||||
(defn- lines [indent & lines]
|
||||
(apply str (map (prepend indent) (flatten lines))))
|
||||
|
||||
(defn- lines-collection [indent open close f value]
|
||||
(let [items (mapv f value)]
|
||||
(case (count items)
|
||||
0 (str open close)
|
||||
1 (str open (first items) close)
|
||||
(lines indent
|
||||
(str open (first items))
|
||||
(map (prepend " ") (init (rest items)))
|
||||
(str " " (last items) close)))))
|
||||
|
||||
(defn- remove-generated [value]
|
||||
(clojure.string/replace value #"__[0-9]+#" "#"))
|
||||
|
||||
(defn- render [value]
|
||||
(cond
|
||||
(fn? value) (str "#function[" (clojure.string/replace (str (type value)) #"fn__[0-9]+" "fn") "]")
|
||||
(delay? value) (str "#delay")
|
||||
(instance? clojure.lang.Namespace value) (str "#namespace[" (ns-name value) "]")
|
||||
(instance? Throwable value) (str (.getSimpleName (type value)) ": " (.getMessage value))
|
||||
:else (remove-generated (pr-str value))))
|
||||
|
||||
(defn- prettify
|
||||
([value] (prettify value "\n "))
|
||||
([value indent]
|
||||
(let [r-value (render value)]
|
||||
(cond
|
||||
(< (count (str indent r-value)) 80) r-value
|
||||
(vector? value) (lines-collection indent "[" "]" #(clojure.string/triml (prettify % (str indent " "))) value)
|
||||
(seq? value) (lines-collection indent "(" ")" #(clojure.string/triml (prettify % (str indent " "))) value)
|
||||
(map? value) (lines-collection
|
||||
indent "{" "}"
|
||||
(fn [[key value]] (str (render key) " " (prettify value (str indent " "))))
|
||||
value)
|
||||
:else r-value))))
|
||||
|
||||
(defn example' [description & expressions]
|
||||
{:pre [(not (empty? expressions))]}
|
||||
(println (str " " description ": "))
|
||||
(letfn [(run [expression]
|
||||
(let [[output value] (with-out-str-and-value expression)]
|
||||
(println " " (render expression) "->" (prettify value))
|
||||
(if-not (empty? output)
|
||||
(mapv #(println " >" %) (clojure.string/split-lines output)))))]
|
||||
(mapv run expressions)))
|
||||
|
||||
(defmacro example [description & expressions]
|
||||
`(apply example' ~description (quote ~expressions)))
|
||||
|
||||
(defn with-in-file [file action]
|
||||
(with-in-str (slurp file) (action)))
|
||||
90
clojure/examples/1_1_intro.clj
Normal file
90
clojure/examples/1_1_intro.clj
Normal file
@@ -0,0 +1,90 @@
|
||||
(chapter "Expressions and variables")
|
||||
|
||||
(section "Numbers and Expressions")
|
||||
(example "Literals"
|
||||
2
|
||||
-10
|
||||
"Hello world"
|
||||
true)
|
||||
(example "Simple expressions"
|
||||
(+ 2 3)
|
||||
(- 2 3)
|
||||
(* 2 3)
|
||||
(/ 2 3))
|
||||
(example "Compound expressions"
|
||||
(+ 2 (- 3 1)))
|
||||
(example "Variable-args functions"
|
||||
(- 10 1 2 3))
|
||||
(example "Special cases"
|
||||
(- 10))
|
||||
(example "Nullary functions"
|
||||
(+))
|
||||
|
||||
(section "Equality")
|
||||
(example "Generic equality"
|
||||
(= (* 2 3) 6)
|
||||
(= (* 2 3) 6.0)
|
||||
(= (* 2 3) 5)
|
||||
(= (* 2 3) (+ 3 3)))
|
||||
(example "Number equality"
|
||||
(== (* 2 3) 6)
|
||||
(== (* 2 3) 6.0)
|
||||
(== (* 2 3) 5)
|
||||
(== (* 2 3) (+ 3 3)))
|
||||
(example "Reference equality"
|
||||
(identical? (* 2 3) (+ 3 3))
|
||||
(identical? (* 2 300) (+ 300 300)))
|
||||
(example "Inequality"
|
||||
(not (== (* 2 3) (+ 3 3))))
|
||||
|
||||
(section "Booleans")
|
||||
(example "Literals"
|
||||
true
|
||||
false)
|
||||
(example "not"
|
||||
(not true)
|
||||
(not false))
|
||||
(example "and"
|
||||
(and true true)
|
||||
(and true false)
|
||||
(and false false)
|
||||
(and true true false false))
|
||||
(example "or"
|
||||
(or true true)
|
||||
(or true false)
|
||||
(or false false)
|
||||
(or true true false false))
|
||||
|
||||
(section "Variables")
|
||||
(example "Define"
|
||||
(def x 10))
|
||||
(example "Use"
|
||||
(* x (+ x 3)))
|
||||
(example "Output"
|
||||
(println x))
|
||||
|
||||
(section "First-order functions")
|
||||
(example "Output function"
|
||||
+)
|
||||
(example "Assign function"
|
||||
(def add +))
|
||||
(example "Variable as a function"
|
||||
(add 10 20 30))
|
||||
|
||||
(section "Simple types")
|
||||
(example "Integers"
|
||||
(type 10))
|
||||
(example "Floating-point"
|
||||
(type 10.0))
|
||||
(example "Rational"
|
||||
(type (/ 2 3))
|
||||
(type 2/3))
|
||||
(example "BigInt"
|
||||
(type 2N))
|
||||
(example "String"
|
||||
(type "Hello"))
|
||||
(example "Booleans"
|
||||
(type true))
|
||||
(example "Type conversion"
|
||||
(double 2/3)
|
||||
(int 2/3))
|
||||
91
clojure/examples/1_2_functions.clj
Normal file
91
clojure/examples/1_2_functions.clj
Normal file
@@ -0,0 +1,91 @@
|
||||
(chapter "Custom Functions")
|
||||
|
||||
(section "Simple Functions")
|
||||
(example "Define function"
|
||||
(defn square [x] (* x x)))(example "Use function"
|
||||
(square 8))
|
||||
(example "Multi-arg functions"
|
||||
(defn mul-add [a b c] (+ (* a b) c))
|
||||
(mul-add 3 10 5))
|
||||
(example "Nullary function"
|
||||
(defn nullary [] 10)
|
||||
(nullary))
|
||||
(example "Anonymous functions"
|
||||
((fn [x] (+ x x)) 10)
|
||||
(#(+ % %) 10)
|
||||
(#(+ %1 %2) 10 20))
|
||||
(example "Functions as values"
|
||||
(defn twice [f] (fn [a] (f (f a))))
|
||||
((twice square) 3))
|
||||
|
||||
(section "Recursive Functions")
|
||||
(example "Recursive Fibonacci"
|
||||
(defn rec-fib [n]
|
||||
(cond
|
||||
(== 0 n) 1
|
||||
(== 1 n) 1
|
||||
:else (+ (rec-fib (- n 1))
|
||||
(rec-fib (- n 2)))))
|
||||
(rec-fib 40))
|
||||
(example "Memoized Fibonacci"
|
||||
(def mem-fib
|
||||
(memoize
|
||||
(fn [n]
|
||||
(cond
|
||||
(== 0 n) 1
|
||||
(== 1 n) 1
|
||||
:else (+ (mem-fib (- n 1)) (mem-fib (- n 2)))))))
|
||||
(mem-fib 90))
|
||||
(example "Tail-recursive Fibonacci"
|
||||
(defn iter-fib [n]
|
||||
(letfn [(iter-fib' [n a b]
|
||||
(if (== 0 n)
|
||||
a
|
||||
(iter-fib' (- n 1) b (+' a b))))]
|
||||
(iter-fib' n 1 1)))
|
||||
(iter-fib 90)
|
||||
(iter-fib 10000)
|
||||
(defn iter-fib-recur [n]
|
||||
(letfn [(iter-fib' [n a b]
|
||||
(if (== 0 n)
|
||||
a
|
||||
(recur (- n 1) b (+' a b))))]
|
||||
(iter-fib' n 1 1)))
|
||||
(iter-fib-recur 10000))
|
||||
(example "Explicit loop Fibonacci"
|
||||
(defn loop-fib [n]
|
||||
(loop [n n a 1 b 1]
|
||||
(if (== 0 n)
|
||||
a
|
||||
(recur (- n 1) b (+ a b)))))
|
||||
(loop-fib 90))
|
||||
|
||||
(section "Pre and Post conditions")
|
||||
(example "Fast power"
|
||||
(defn power
|
||||
"Raises a to the b-th power"
|
||||
[a b]
|
||||
{:pre [(<= 0 b)]
|
||||
:post [(or (zero? b) (zero? a) (zero? (rem % a)))]}
|
||||
(cond
|
||||
(zero? b) 1
|
||||
(even? b) (power (* a a) (quot b 2))
|
||||
(odd? b) (* a (power a (dec b))))))
|
||||
(example "Pre and postconditions ok"
|
||||
(power 2 5)
|
||||
(power 2 0)
|
||||
(power 0 2))
|
||||
(example "Precondition violated"
|
||||
(power 2 -5))
|
||||
(example "Invalid postcondition"
|
||||
(defn ipower
|
||||
[a b]
|
||||
{:pre [(<= 0 b)]
|
||||
:post [(zero? (rem % a)) (<= 0 %)]}
|
||||
(power a b)))
|
||||
(example "First part of invalid postcondition violated"
|
||||
(ipower 2 0)
|
||||
(power 2 0))
|
||||
(example "Second part of invalid postcondition violated"
|
||||
(ipower -2 3)
|
||||
(power -2 3))
|
||||
67
clojure/examples/1_3_lists.clj
Normal file
67
clojure/examples/1_3_lists.clj
Normal file
@@ -0,0 +1,67 @@
|
||||
(chapter "Lists")
|
||||
|
||||
(section "Definition and tests")
|
||||
(example "Lists"
|
||||
(list 1 2)
|
||||
(list 1 2 "Hello" 3 4)
|
||||
(list))
|
||||
(example "List type"
|
||||
(type (list 1 2))
|
||||
(type (list))
|
||||
(type ()))
|
||||
(example "List variable"
|
||||
(def lst (list 1 2 "Hello" 3 4)))
|
||||
(example "List test"
|
||||
(list? lst)
|
||||
(list? (list 1))
|
||||
(list? ()))
|
||||
|
||||
(section "Operations")
|
||||
(example "Length"
|
||||
(count lst))
|
||||
(example "Head"
|
||||
(first lst))
|
||||
(example "Tail"
|
||||
(rest lst))
|
||||
(example "Last"
|
||||
(last lst))
|
||||
(example "Indexing"
|
||||
(nth lst 0)
|
||||
(nth lst 1)
|
||||
(nth lst 2)
|
||||
(nth lst 10)
|
||||
(nth lst 10 "none"))
|
||||
(example "Add element"
|
||||
(cons 0 lst))
|
||||
(example "Add elements"
|
||||
(conj lst 100 200))
|
||||
(example "Emptiness test"
|
||||
(empty? (rest (list 1)))
|
||||
(empty? (list))
|
||||
(empty? ())
|
||||
(empty? lst))
|
||||
|
||||
(section "Folds")
|
||||
(example "Left fold"
|
||||
(defn foldLeft
|
||||
"Applies a binary operator f to a zero value and all elements of the list, going left to right"
|
||||
[zero f items]
|
||||
(if (empty? items)
|
||||
zero
|
||||
(foldLeft (f zero (first items)) f (rest items))))
|
||||
(foldLeft 0 - (list 1 2 3 4)))
|
||||
(example "Right fold"
|
||||
(defn foldRight [zero f items]
|
||||
"Applies a binary operator f to a zero value and all elements of the list, going right to left"
|
||||
(if (empty? items)
|
||||
zero
|
||||
(f (first items) (foldRight zero f (rest items)))))
|
||||
(foldRight 0 - (list 1 2 3 4)))
|
||||
(example "Tail-call optimised left fold"
|
||||
(defn foldLeft' [zero f items]
|
||||
(if (empty? items)
|
||||
zero
|
||||
(recur (f zero (first items)) f (rest items))))
|
||||
(count (range 1000000))
|
||||
(foldLeft 0 + (range 1000000))
|
||||
(foldLeft' 0 + (range 1000000)))
|
||||
22
clojure/examples/1_4_vectors.clj
Normal file
22
clojure/examples/1_4_vectors.clj
Normal file
@@ -0,0 +1,22 @@
|
||||
(chapter "Vectors")
|
||||
(example "Vectors"
|
||||
(vector 1 2)
|
||||
(vector 1 2 "Hello" 3 4)
|
||||
[1 2]
|
||||
(def vect [1 2 "Hello" 3 4]))
|
||||
(example "Vector type"
|
||||
(type [1 2])
|
||||
(type (vector))
|
||||
(type []))
|
||||
(example "Queries"
|
||||
(count vect)
|
||||
(nth vect 2)
|
||||
(nth vect 20 "none")
|
||||
(vect 2)
|
||||
(vect 10))
|
||||
(example "Modifications"
|
||||
(conj vect 100 200)
|
||||
(peek vect)
|
||||
(pop vect)
|
||||
(assoc vect 0 100)
|
||||
(assoc vect 0 100 2 200))
|
||||
42
clojure/examples/1_5_functions-2.clj
Normal file
42
clojure/examples/1_5_functions-2.clj
Normal file
@@ -0,0 +1,42 @@
|
||||
(chapter "High-order Functions")
|
||||
|
||||
(section "Ordinary functions")
|
||||
(example "Identity function"
|
||||
(identity [1 2 3]))
|
||||
(example "Constant function"
|
||||
((constantly 10) 20 30))
|
||||
|
||||
(section "High-order functions")
|
||||
(example "Function composition"
|
||||
((comp square square square) 2)
|
||||
((comp #(* % 2) #(+ % 2)) 10))
|
||||
(example "Currying"
|
||||
(def sum (partial foldLeft' 0 +))
|
||||
(sum [1 2 3]))
|
||||
(example "Reduce"
|
||||
(def sum' (partial reduce + 0))
|
||||
(sum' [1 2 3]))
|
||||
(example "Application"
|
||||
(apply + [1 2 3]))
|
||||
(example "Map"
|
||||
(mapv inc (range 10)))
|
||||
(example "Juxtaposition"
|
||||
((juxt + - * /) 1 2 3 4))
|
||||
|
||||
(section "Variable-argument functions")
|
||||
(example "Sum of squares"
|
||||
(defn sumSquares [& xs] (apply + (map square xs)))
|
||||
(sumSquares 3 4))
|
||||
(example "Sum of squares (anonymous)"
|
||||
(#(apply + (map square %&)) 3 4))
|
||||
|
||||
(example "Explicit multi-arity"
|
||||
(defn countArgs
|
||||
([] "zero")
|
||||
([a] "one")
|
||||
([a b] "two")
|
||||
([a b & as] (str (+ 2 (count as)))))
|
||||
(countArgs)
|
||||
(countArgs 1)
|
||||
(countArgs 1 2)
|
||||
(countArgs 1 2 3))
|
||||
Reference in New Issue
Block a user