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