Transcript Clojure 3

Clojure 3
26-Jul-16
Clojure errors

(NO_SOURCE_FILE:12)


java.lang.Exception: EOF while reading (test.clj:139)





Useless--just means you’re running from the REPL shell
You have an unclosed parenthesis somewhere
Use a good text editor!
In jEdit, Control-A Control-I will make the error obvious
user=> (map (fn[x] (x * x)) (take 10 (iterate inc 1)))
java.lang.ClassCastException: java.lang.Integer cannot be
cast to clojure.lang.IFn
Sequences


In Clojure, almost every collection is a sequence
user=> (cons 5 [1 2 3])
(5 1 2 3) ; Not [5 1 2 3]





user=> (class '(1 2 3))
clojure.lang.PersistentList
user=> (class [1 2 3])
clojure.lang.LazilyPersistentVector
user=> (class (cons 5 [1 2 3]))
clojure.lang.Cons
user=> (class (rest (cons 5 [1 2 3])))
clojure.lang.LazilyPersistentVector$ChunkedSeq
Most of the time you don’t care what kind of a sequence it is
Persistence and laziness

In Functional Programming, a persistent data structure
is one that is itself immutable, but can be modified to
create a “new” data structure


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

This allows you to have “infinite” data structures
range, take, and drop






user=> (range 10)
(0 1 2 3 4 5 6 7 8 9)
user=> (range 1 10)
(1 2 3 4 5 6 7 8 9)
user=> (range 0 20 3)
(0 3 6 9 12 15 18)
user=> (range 10 20)
(10 11 12 13 14 15 16 17 18 19)
user=> (take 4 (range 10 20))
(10 11 12 13)
user=> (drop 4 (range 10 20))
(14 15 16 17 18 19)






user=> (range 1 10)
(1 2 3 4 5 6 7 8 9)
user=> (take 20 (range 1 10))
(1 2 3 4 5 6 7 8 9)
user=> (drop 20 (range 1 10))
()
user=> (take 4 "abcdefg")
(\a \b \c \d)
user=> (str (take 4 "abcdefg"))
"clojure.lang.LazySeq@3babc3"
user=> (apply str (take 4 "abcdefg"))
"abcd"
iterate





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





user=> (take 10 (iterate (fn [x] (* 2 x)) 2))
(2 4 8 16 32 64 128 256 512 1024)
(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 1 1 1 1)
user=> (nth (iterate collatz-1 7) 4)
17
Fibonacci numbers





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 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







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






user=> (defn hypotenuse [a b]
(let [a2 (* a a) b2 (* b b)]
(Math/sqrt (+ a2 b2)) ) )
#'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




user=> (format "%d + %d is %d\n" 3 4 7)
"3 + 4 is 7\n”
user=> (print (format "%d + %d is %d\n" 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

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.


user=> (take 12 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))
([1 0] [2 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/clojure.core-api.html#clojure.core/for
List comprehensions II





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





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



(partial f arg1 arg2 arg3 & 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







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



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





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

Java is an object-oriented language



You have a lot of classes available to you
You should not write your own Stack class!
Apparently, something similar is going on in Clojure



Clojure depends heavily on recursion
There are a lot of built-in functions that are recursive
You should avoid recursion if Clojure will do it for you
Zip





(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 zip4 (partial zip [1 2 3 4]))
#'user/zip4
user=> (zip4 "abcde")
((1 \a) (2 \b) (3 \c) (4 \d))
Best reference

http://clojure.github.com/clojure/clojure.core-api.html
The End