Clojure 4 Sequences 18 Dec21 Clojure errors n

  • Slides: 22
Download presentation
Clojure 4 Sequences 18 -Dec-21

Clojure 4 Sequences 18 -Dec-21

Clojure errors n (NO_SOURCE_FILE: 12) n n java. lang. Exception: EOF while reading (test.

Clojure errors n (NO_SOURCE_FILE: 12) n n java. lang. Exception: EOF while reading (test. clj: 139) n n n Useless--just means you’re running from the REPL shell You have an unclosed parenthesis somewhere Use a good text editor! In j. Edit, Control-A Control-I will make the error obvious user=> (map (fn[x] (x * x)) (take 10 (iterate inc 1))) java. lang. Class. Cast. Exception: java. lang. Integer cannot be cast to clojure. lang. IFn

Sequences n n In Clojure, almost every collection is a sequence user=> (cons 5

Sequences n n In Clojure, almost every collection is a sequence user=> (cons 5 [1 2 3]) (5 1 2 3) ; Not [5 1 2 3] n n n user=> (class '(1 2 3)) clojure. lang. Persistent. List user=> (class [1 2 3]) clojure. lang. Lazily. Persistent. Vector user=> (class (cons 5 [1 2 3])) clojure. lang. Cons user=> (class (rest (cons 5 [1 2 3]))) clojure. lang. Lazily. Persistent. Vector$Chunked. Seq Most common operations apply to all kinds of sequences n If necessary, use the seq function to convert any sequence to a seq

Persistence and laziness n In Functional Programming, a persistent data structure is one that

Persistence and laziness n In Functional Programming, a persistent data structure is one that is itself immutable, but can be modified to create a “new” data structure n n The original and the new data structure share structure to minimize copying time and wasted storage A lazy data structure is one where parts of it do not exist until they are accessed n This allows you to have “infinite” data structures

range, take, and drop n n n user=> (0 1 2 user=> (1 2

range, take, and drop n n n user=> (0 1 2 user=> (1 2 3 user=> (0 3 6 (range 10) 3 4 5 6 7 8 9) (range 1 10) 4 5 6 7 8 9) (range 0 20 3) 9 12 15 18) user=> (10 11 19) user=> (10 11 user=> (14 15 (range 10 20) 12 13 14 15 16 17 18 n n n (take 4 (range 10 20)) 12 13) n (drop 4 (range 10 20)) 16 17 18 19) user=> (1 2 3 user=> () (range 1 10) 4 5 6 7 8 9) (take 20 (range 1 10)) 4 5 6 7 8 9) (drop 20 (range 1 10)) user=> (take 4 "abcdefg") (a b c d) user=> (str (take 4 "abcdefg")) "clojure. lang. Lazy. Seq@3 babc 3" user=> (apply str (take 4 "abcdefg")) "abcd"

iterate n n n iterate takes a function f and a starting value n,

iterate n n n iterate takes a function f and a starting value n, and lazily produces the infinite series (n, f(n), f(f(n)), f(f(f(n))), . . . ) ; Don’t try this! user=> (iterate inc 1) (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17. . . ) ; But this is okay user=> (take 5 (iterate inc 1)) (1 2 3 4 5) ; Don’t try this! user=> (drop 5 (iterate inc 1)) (6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21. . . ) ; But this is okay user=> (take 5 (drop 1000 (iterate inc 1))) (1001 1002 1003 1004 1005)

Fun with iterate n n n user=> (take 10 (iterate (fn [x] (* 2

Fun with iterate n n n user=> (take 10 (iterate (fn [x] (* 2 x)) (2 4 8 16 32 64 128 256 512 1024) 2)) (defn collatz-1 [n] (cond (= n 1) 1 (even? n) (/ n 2) (odd? n) (inc (* 3 n)) ) ) user=> (take 5 (iterate collatz-1 7)) (7 22 11 34 17) user=> (take 25 (iterate collatz-1 7)) (7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1 1 1 1 1) user=> (nth (iterate collatz-1 7) 4) 17

Fibonacci numbers n n n user=> (defn next-pair [pair] (list (second pair) (+ (first

Fibonacci numbers n n n user=> (defn next-pair [pair] (list (second pair) (+ (first pair) (second pair)))) #'user/next-pair user=> (next-pair '(1 1)) (1 2) user=> (next-pair '(1 2)) (2 3) user=> (take 10 (iterate next-pair '(0 1))) ((0 1) (1 2) (2 3) (3 5) (5 8) (8 13) (13 21) (21 34) (34 55)) user=> (map second (take 10 (iterate next-pair '(0 1)))) (1 1 2 3 5 8 13 21 34 55)

Prime numbers n n n n user=> (defn divides [d n] (integer? (/ n

Prime numbers n n n n user=> (defn divides [d n] (integer? (/ n d))) #'user/divides user=> (divides 4 24) true user=> (divides 5 24) false user=> (defn prime [n] (not-any? (fn [d] (divides d n)) (range 2 (dec n)))) #'user/prime user=> (take 20 (filter prime (iterate inc 2))) (2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71) user=> (defn composite [n] (some (fn [d] (divides d n)) (range 2 (dec n)))) #'user/composite user=> (take 20 (filter composite (iterate inc 1))) (4 6 8 9 10 12 14 15 16 18 20 21 22 24 25 26 27 28 30 32)

let and letfn n n n user=> (defn hypotenuse [a b] (let [a 2

let and letfn n n n user=> (defn hypotenuse [a b] (let [a 2 (* a a) b 2 (* b b)] (Math/sqrt (+ a 2 b 2)) ) ) #'user/hypotenuse user=> (hypotenuse 3 4) 5. 0 user=> (hypotenuse 1 1) 1. 4142135623730951 user=> (defn hypotenuse [a b] (letfn [(square [n] (* n n))] (Math/sqrt (+ (square a) (square b))))) #'user/hypotenuse user=> (hypotenuse 3 4) 5. 0 user=> (hypotenuse 1 1) 1. 4142135623730951

Debugging with do n n user=> (format "%d + %d is %dn" 3 4

Debugging with do n n user=> (format "%d + %d is %dn" 3 4 7) "3 + 4 is 7n" user=> (print (format "%d + %d is %dn" 3 4 7)) 3 + 4 is 7 nil user=> (defn hypotenuse [a b] (letfn [(square [n] (* n n))] (do (println (format "a = %d, b = %d" a b)) (Math/sqrt (+ (square a) (square b))) ) #'user/hypotenuse user=> (hypotenuse 3 4) a = 3, b = 4 5. 0

List comprehensions I n for macro Usage: (for seq-exprs body-expr) List comprehension. Takes a

List comprehensions I n for macro Usage: (for seq-exprs body-expr) List comprehension. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost fastest, and nested coll-exprs can refer to bindings created in prior binding-forms. Supported modifiers are: : let [binding-form expr. . . ], : while test, : when test. n n user=> (take 12 (for [x (range 10000) y (range 1000000) : while (< y x)] [x y])) ([1 0] [2 1] [3 0] [3 1] [3 2] [4 0] [4 1] [4 2] [4 3] [5 0] [5 1]) Source: http: //clojure. github. com/clojure. core-api. html#clojure. core/for

List comprehensions II n n n user=> (map (fn[x] (* x x)) (take 10

List comprehensions II n n n user=> (map (fn[x] (* x x)) (take 10 (iterate inc 1))) (1 4 9 16 25 36 49 64 81 100) user=> (for [x (take 10 (iterate inc 1))] (* x x)) (1 4 9 16 25 36 49 64 81 100) user=> (take 10 (for [x (iterate inc 1)] (* x x))) (1 4 9 16 25 36 49 64 81 100) user=> (for [x (iterate inc 1) : while (< x 11)] (* x x)) (1 4 9 16 25 36 49 64 81 100) user=> (for [x (range 1 11)] (* x x)) (1 4 9 16 25 36 49 64 81 100)

List comprehensions III n n n user=> (for [x (range 1 11) : when

List comprehensions III n n n user=> (for [x (range 1 11) : when (even? x)] (* x x)) (4 16 36 64 100) user=> (take 10 (for [x (iterate inc 1) : when (even? x)] (* x x))) (4 16 36 64 100 144 196 256 324 400) ; Don't do this: user=> (for [x (iterate inc 1) : when (even? x)] (* x x)) (4 16 36 64 100 144 196 256 324 400 484 576 676 784. . . user=> (for [x "abcde" y [1 2]] [x y]) ([a 1] [a 2] [b 1] [b 2] [c 1] [c 2] [d 1] [d 2] [e 1] [e 2]) user=> (for [word ["the" "quick" "brown" "fox" "jumps"]] (format "Word: %s" word) ) ("Word: the" "Word: quick" "Word: brown" "Word: fox" "Word: jumps")

Partial functions n n n (partial f arg 1 arg 2 arg 3 &

Partial functions n n n (partial f arg 1 arg 2 arg 3 & more) Takes a function f and fewer than the normal arguments to f, and returns a fn that takes a variable number of additional args. When called, the returned function calls f with args + additional args. user=> (def hundred-times (partial * 100)) #'user/hundred-times user=> (hundred-times 5) 500

Prime, revisited n n n n user=> (defn prime [n] (not-any? (fn [d] (divides

Prime, revisited n n n n user=> (defn prime [n] (not-any? (fn [d] (divides d n)) (range 2 (dec n)))) #'user/prime user=> (defn divisible [n d] (integer? (/ n d))) #'user/divisible user=> (divisible 24 3) true user=> (divisible 24 5) false user=> (defn prime [n] (not-any? (partial divisible n) (range 2 (dec n)))) #'user/prime user=> (prime 21) false user=> (prime 19) true

Member n n n user=> (defn member [e coll] (cond (empty? coll) false (=

Member n n n user=> (defn member [e coll] (cond (empty? coll) false (= e (first coll)) true : else (member e (rest coll)) ) ) #'user/member user=> (member 5 (range 1 10)) true user=> (member 5 (range 10 20)) false

Member, revisited n n n user=> (some (partial = 5) (range 1 10)) true

Member, revisited n n n user=> (some (partial = 5) (range 1 10)) true user=> (some (partial = 5) (range 10 20)) nil user=> (defn member [e coll] (some (partial = e) coll)) #'user/member user=> (member 5 (range 1 10)) true user=> (member 5 (range 10 20)) nil

Avoiding recursion n Java is an object-oriented language n n n You have a

Avoiding recursion n Java is an object-oriented language n n n You have a lot of classes available to you You should not write your own Stack class! Clojure is a very recursive language n n There a lot of built-in functions that are recursive You should avoid recursion if Clojure will do it for you

Zip n n n (defn zip [a b] (if (or (empty? a) (empty? b))

Zip n n n (defn zip [a b] (if (or (empty? a) (empty? b)) () (cons (list (first a) (first b)) (zip (rest a) (rest b))) ) ) user=> (zip [1 2 3 4] [: a : b : c]) ((1 : a) (2 : b) (3 : c)) user=> (zip '(1 2 3 4) '(: a : b : c)) ((1 : a) (2 : b) (3 : c)) user=> (def zip 4 (partial zip [1 2 3 4])) #'user/zip 4 user=> (zip 4 "abcde") ((1 a) (2 b) (3 c) (4 d))

Best reference n http: //clojure. github. com/clojure. core-api. html

Best reference n http: //clojure. github. com/clojure. core-api. html

The End

The End