rlm@10
|
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
rlm@10
|
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
rlm@10
|
3 ;;
|
rlm@10
|
4 ;; Stream application examples
|
rlm@10
|
5 ;;
|
rlm@10
|
6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
rlm@10
|
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
rlm@10
|
8
|
rlm@10
|
9 (ns
|
rlm@10
|
10 #^{:author "Konrad Hinsen"
|
rlm@10
|
11 :skip-wiki true
|
rlm@10
|
12 :doc "Examples for data streams"}
|
rlm@10
|
13 clojure.contrib.stream-utils.examples
|
rlm@10
|
14 (:refer-clojure :exclude (deftype))
|
rlm@10
|
15 (:use [clojure.contrib.stream-utils
|
rlm@10
|
16 :only (defst stream-next
|
rlm@10
|
17 pick pick-all
|
rlm@10
|
18 stream-type defstream
|
rlm@10
|
19 stream-drop stream-map stream-filter stream-flatten)])
|
rlm@10
|
20 (:use [clojure.contrib.monads :only (domonad)])
|
rlm@10
|
21 (:use [clojure.contrib.types :only (deftype)])
|
rlm@10
|
22 (:require [clojure.contrib.generic.collection :as gc]))
|
rlm@10
|
23
|
rlm@10
|
24 ;
|
rlm@10
|
25 ; Define a stream of Fibonacci numbers
|
rlm@10
|
26 ;
|
rlm@10
|
27 (deftype ::fib-stream last-two-fib)
|
rlm@10
|
28
|
rlm@10
|
29 (defstream ::fib-stream
|
rlm@10
|
30 [fs]
|
rlm@10
|
31 (let [[n1 n2] fs]
|
rlm@10
|
32 [n1 (last-two-fib [n2 (+ n1 n2)])]))
|
rlm@10
|
33
|
rlm@10
|
34 (def fib-stream (last-two-fib [0 1]))
|
rlm@10
|
35
|
rlm@10
|
36 (take 10 (gc/seq fib-stream))
|
rlm@10
|
37
|
rlm@10
|
38 ;
|
rlm@10
|
39 ; A simple random number generator, implemented as a stream
|
rlm@10
|
40 ;
|
rlm@10
|
41 (deftype ::random-seed rng-seed vector seq)
|
rlm@10
|
42
|
rlm@10
|
43 (defstream ::random-seed
|
rlm@10
|
44 [seed]
|
rlm@10
|
45 (let [[seed] seed
|
rlm@10
|
46 m 259200
|
rlm@10
|
47 value (/ (float seed) (float m))
|
rlm@10
|
48 next (rem (+ 54773 (* 7141 seed)) m)]
|
rlm@10
|
49 [value (rng-seed next)]))
|
rlm@10
|
50
|
rlm@10
|
51 (take 10 (gc/seq (rng-seed 1)))
|
rlm@10
|
52
|
rlm@10
|
53 ;
|
rlm@10
|
54 ; Various stream utilities
|
rlm@10
|
55 ;
|
rlm@10
|
56 (take 10 (gc/seq (stream-drop 10 (rng-seed 1))))
|
rlm@10
|
57 (gc/seq (stream-map inc (range 5)))
|
rlm@10
|
58 (gc/seq (stream-filter odd? (range 10)))
|
rlm@10
|
59 (gc/seq (stream-flatten (partition 3 (range 9))))
|
rlm@10
|
60
|
rlm@10
|
61 ;
|
rlm@10
|
62 ; Stream transformers
|
rlm@10
|
63 ;
|
rlm@10
|
64
|
rlm@10
|
65 ; Transform a stream of numbers into a stream of sums of two
|
rlm@10
|
66 ; consecutive numbers.
|
rlm@10
|
67 (defst sum-two [] [xs]
|
rlm@10
|
68 (domonad
|
rlm@10
|
69 [x1 (pick xs)
|
rlm@10
|
70 x2 (pick xs)]
|
rlm@10
|
71 (+ x1 x2)))
|
rlm@10
|
72
|
rlm@10
|
73 (def s (sum-two '(1 2 3 4 5 6 7 8)))
|
rlm@10
|
74
|
rlm@10
|
75 (let [[v1 s] (stream-next s)]
|
rlm@10
|
76 (let [[v2 s] (stream-next s)]
|
rlm@10
|
77 (let [[v3 s] (stream-next s)]
|
rlm@10
|
78 (let [[v4 s] (stream-next s)]
|
rlm@10
|
79 (let [[v5 s] (stream-next s)]
|
rlm@10
|
80 [v1 v2 v3 v4 v5])))))
|
rlm@10
|
81
|
rlm@10
|
82 (gc/seq s)
|
rlm@10
|
83
|
rlm@10
|
84 ; Map (for a single stream) written as a stream transformer
|
rlm@10
|
85 (defst my-map-1 [f] [xs]
|
rlm@10
|
86 (domonad
|
rlm@10
|
87 [x (pick xs)]
|
rlm@10
|
88 (f x)))
|
rlm@10
|
89
|
rlm@10
|
90 (gc/seq (my-map-1 inc [1 2 3]))
|
rlm@10
|
91
|
rlm@10
|
92 ; Map for two stream arguments
|
rlm@10
|
93 (defst my-map-2 [f] [xs ys]
|
rlm@10
|
94 (domonad
|
rlm@10
|
95 [x (pick xs)
|
rlm@10
|
96 y (pick ys)]
|
rlm@10
|
97 (f x y)))
|
rlm@10
|
98
|
rlm@10
|
99 (gc/seq (my-map-2 + '(1 2 3 4) '(10 20 30 40)))
|
rlm@10
|
100
|
rlm@10
|
101 ; Map for any number of stream arguments
|
rlm@10
|
102 (defst my-map [f] [& streams]
|
rlm@10
|
103 (domonad
|
rlm@10
|
104 [vs pick-all]
|
rlm@10
|
105 (apply f vs)))
|
rlm@10
|
106
|
rlm@10
|
107 (gc/seq (my-map inc [1 2 3]))
|
rlm@10
|
108 (gc/seq (my-map + '(1 2 3 4) '(10 20 30 40)))
|
rlm@10
|
109
|
rlm@10
|
110 ; Filter written as a stream transformer
|
rlm@10
|
111 (defst my-filter [p] [xs]
|
rlm@10
|
112 (domonad
|
rlm@10
|
113 [x (pick xs) :when (p x)]
|
rlm@10
|
114 x))
|
rlm@10
|
115
|
rlm@10
|
116 (gc/seq (my-filter odd? [1 2 3]))
|
rlm@10
|
117
|