close

Se connecter

Se connecter avec OpenID

Clojure 2

IntégréTéléchargement
Clojure 4
Sequences
13-Nov-15
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 common operations apply to all kinds of sequences

If necessary, use the seq function to convert any sequence to a seq
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=>
(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




(take 4 (range 10 20))
12 13)

(drop 4 (range 10 20))
16 17 18 19)
user=>
(1 2 3
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.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 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 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!
Clojure is a very recursive language


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
Auteur
Документ
Catégorie
Без категории
Affichages
6
Taille du fichier
320 Кб
Étiquettes
1/--Pages
signaler