|
1 | | -;;; Load this file into LightTable (using LightTable's workspace tab) |
2 | | -;;; and "make current editor an instarepl" (using LightTable's command |
3 | | -;;; tab). |
| 1 | +;;; Run this file by going to the project directory (the directory |
| 2 | +;;; with 'project.clj' in it) and saying 'lein repl'. |
4 | 3 |
|
5 | 4 | (ns expt1.core |
6 | 5 | (:require [expt1.k2 :as k2 ] |
|
28 | 27 | ;;; / __|___ _ _ ___ _ _(_)__ / _ \| |__ ___ ___ _ ___ _____ _ _ |
29 | 28 | ;;; | (_ / -_) ' \/ -_) '_| / _| | (_) | '_ (_-</ -_) '_\ V / -_) '_| |
30 | 29 | ;;; \___\___|_||_\___|_| |_\__| \___/|_.__/__/\___|_| \_/\___|_| |
31 | | - |
| 30 | +;;; |
32 | 31 |
|
33 | 32 | ;;; The current rx library has no co-monadic operators such as "first" |
34 | 33 | ;;; and "last". Let us make atomic, external collectors for extracting |
|
101 | 100 | (Observable/toObservable [1 2 3]) |
102 | 101 | (.take 2) |
103 | 102 | (subscribe-collectors) |
| 103 | + (pdump) |
104 | 104 | ) |
105 | 105 |
|
106 | 106 | ;;; ___ _ |
|
124 | 124 | (.mapMany |
125 | 125 | #(Observable/toObservable (map (partial + %) [42 43 44]))) |
126 | 126 | (subscribe-collectors) |
| 127 | + (pdump) |
127 | 128 | ) |
128 | 129 |
|
129 | 130 | ;;; Let's operate on strings. |
|
132 | 133 | (Observable/toObservable ["one" "two" "three"]) |
133 | 134 | (.take 2) |
134 | 135 | (subscribe-collectors) |
| 136 | + (pdump) |
135 | 137 | ) |
136 | 138 |
|
137 | 139 | ;;; "seq" explodes strings into lazy sequences of characters: |
|
146 | 148 | (Observable/toObservable ["one" "two" "three"]) |
147 | 149 | (.mapMany #(Observable/toObservable (string-explode %))) |
148 | 150 | (subscribe-collectors) |
| 151 | + (pdump) |
149 | 152 | ) |
150 | 153 |
|
151 | 154 | ;;; __ |
|
167 | 170 | (from-seq ["one" "two" "three"]) |
168 | 171 | (.mapMany (comp from-seq string-explode)) |
169 | 172 | (subscribe-collectors) |
| 173 | + (pdump) |
170 | 174 | ) |
171 | 175 |
|
172 | 176 | ;;; _ |
|
187 | 191 | (.mapMany (comp from-seq string-explode)) |
188 | 192 | (.mapMany return) |
189 | 193 | (subscribe-collectors) |
| 194 | + (pdump) |
190 | 195 | ) |
191 | 196 |
|
192 | 197 | ;;; _ _ _ _ _ |
|
213 | 218 | ;; work on a non-finite oseq. |
214 | 219 |
|
215 | 220 | (subscribe-collectors) |
| 221 | + (pdump) |
216 | 222 | ) |
217 | 223 |
|
218 | 224 | ;;; Package and test. |
|
227 | 233 | (.mapMany (comp from-seq string-explode)) |
228 | 234 | (distinct) |
229 | 235 | (subscribe-collectors) |
| 236 | + (pdump) |
230 | 237 | ) |
231 | 238 |
|
232 | 239 | ;;; _ _ _ _ _ |
|
260 | 267 | (.mapMany from-seq) |
261 | 268 |
|
262 | 269 | (subscribe-collectors) |
| 270 | + (pdump) |
263 | 271 | ) |
264 | 272 |
|
265 | 273 | ;;; Better is to keep a mutable buffer of length one. It could be an atom |
|
287 | 295 | (do |
288 | 296 | (ref-set last-container [x]) |
289 | 297 | (return x))))))) |
290 | | - (subscribe-collectors))) |
| 298 | + (subscribe-collectors) |
| 299 | + (pdump))) |
291 | 300 |
|
292 | 301 | ;;; Package and test: |
293 | 302 |
|
|
308 | 317 | (.mapMany (comp from-seq string-explode)) |
309 | 318 | (distinct-until-changed) |
310 | 319 | (subscribe-collectors) |
| 320 | + (pdump) |
311 | 321 | ) |
312 | 322 |
|
313 | 323 | ;;; It's well-behaved on an empty input: |
|
317 | 327 | (.mapMany (comp from-seq string-explode)) |
318 | 328 | (distinct-until-changed) |
319 | 329 | (subscribe-collectors) |
| 330 | + (pdump) |
320 | 331 | ) |
321 | 332 |
|
322 | | -;;; ___ _ _ ___ _ |
323 | | -;;; / _ \| |_| |_ ___ _ _ | __|_ ____ _ _ __ _ __| |___ ___ |
324 | | -;;; | (_) | _| ' \/ -_) '_| | _|\ \ / _` | ' \| '_ \ / -_|_-< |
325 | | -;;; \___/ \__|_||_\___|_| |___/_\_\__,_|_|_|_| .__/_\___/__/ |
326 | | -;;; |_| |
327 | | - |
328 | 333 | (defn flip [f2] (fn [x y] (f2 y x))) |
329 | 334 |
|
| 335 | +;;; ___ _ |
| 336 | +;;; / __|_ _ _ _ __| |_ _ _ ___ _ _ ___ _ _ ___ |
| 337 | +;;; \__ \ || | ' \/ _| ' \| '_/ _ \ ' \/ _ \ || (_-< |
| 338 | +;;; |___/\_, |_||_\__|_||_|_| \___/_||_\___/\_,_/__/ |
| 339 | +;;; |__/ |
| 340 | +;;; ___ _ _ _ |
| 341 | +;;; / _ \| |__ ___ ___ _ ___ ____ _| |__| |___ |
| 342 | +;;; | (_) | '_ (_-</ -_) '_\ V / _` | '_ \ / -_) |
| 343 | +;;; \___/|_.__/__/\___|_| \_/\__,_|_.__/_\___| |
| 344 | +;;; |
| 345 | + |
330 | 346 | (defn customObservableBlocking [] |
331 | 347 | "A custom Observable whose 'subscribe' method does not return until |
332 | 348 | the observable completes, that is, a 'blocking' observable. |
|
350 | 366 | (.map (partial (flip clojure.string/split) #"_")) |
351 | 367 | (.map (fn [[a b]] [a (Integer/parseInt b)])) |
352 | 368 | (.filter (fn [[a b]] (= 0 (mod b 7)))) |
353 | | - (subscribe-collectors)) |
| 369 | + (subscribe-collectors) |
| 370 | + (pdump) |
| 371 | + ) |
| 372 | + |
| 373 | +;;; _ _ |
| 374 | +;;; /_\ ____ _ _ _ __| |_ _ _ ___ _ _ ___ _ _ ___ |
| 375 | +;;; / _ \ (_-< || | ' \/ _| ' \| '_/ _ \ ' \/ _ \ || (_-< |
| 376 | +;;; /_/ \_\/__/\_, |_||_\__|_||_|_| \___/_||_\___/\_,_/__/ |
| 377 | +;;; |__/ |
| 378 | +;;; ___ _ _ _ |
| 379 | +;;; / _ \| |__ ___ ___ _ ___ ____ _| |__| |___ |
| 380 | +;;; | (_) | '_ (_-</ -_) '_\ V / _` | '_ \ / -_) |
| 381 | +;;; \___/|_.__/__/\___|_| \_/\__,_|_.__/_\___| |
| 382 | +;;; |
354 | 383 |
|
355 | 384 | (defn customObservableNonBlocking [] |
356 | 385 | "A custom Observable whose 'subscribe' method returns immediately |
|
372 | 401 | (.map (partial (flip clojure.string/split) #"_")) |
373 | 402 | (.map (fn [[a b]] [a (Integer/parseInt b)])) |
374 | 403 | (.filter (fn [[a b]] (= 0 (mod b 7)))) |
375 | | - (subscribe-collectors)) |
| 404 | + (subscribe-collectors) |
| 405 | + (pdump) |
| 406 | + ) |
| 407 | + |
| 408 | +;;; _ _ __ __ _ ___ |
| 409 | +;;; /_\ ____ _ _ _ __| |_ \ \ / /__| |__ | _ \__ _ __ _ ___ ___ |
| 410 | +;;; / _ \ (_-< || | ' \/ _| ' \ \ \/\/ / -_) '_ \ | _/ _` / _` / -_|_-< |
| 411 | +;;; /_/ \_\/__/\_, |_||_\__|_||_| \_/\_/\___|_.__/ |_| \__,_\__, \___/__/ |
| 412 | +;;; |__/ |___/ |
376 | 413 |
|
377 | 414 | (defn asynchronousWikipediaArticleObservable [names] |
378 | 415 | "Fetch a list of Wikipedia articles asynchronously. |
|
383 | 420 | (let [f (future |
384 | 421 | (doseq [name names] |
385 | 422 | (-> observer |
| 423 | + ;; Use "enlive" to parse & scrape html: |
386 | 424 | (.onNext |
387 | 425 | (html/html-resource |
388 | 426 | (java.net.URL. |
389 | 427 | (str "http://en.wikipedia.org/wiki/" name)))) |
| 428 | + ;; Netflix originally used strings, but... |
390 | 429 | #_(.onNext (http/get |
391 | 430 | (str "http://en.wikipedia.org/wiki/" name))) |
392 | 431 | ) |
|
398 | 437 | (Subscriptions/create #(future-cancel f)))))) |
399 | 438 |
|
400 | 439 | ;;; There is something in the "Atom" web page that xml/parse does not |
401 | | -;;; like. Rather than debug that, let's find another way to scrape the |
402 | | -;;; web page. |
| 440 | +;;; like. Rather than debug that, let's use enlive |
403 | 441 |
|
404 | | -#_(defn zip-str [s] |
| 442 | +(defn zip-str [s] |
405 | 443 | (zip/xml-zip |
406 | 444 | (xml/parse |
407 | 445 | (java.io.ByteArrayInputStream. |
408 | 446 | (.getBytes s))))) |
409 | 447 |
|
410 | | -(pdump (->> |
411 | | - ((subscribe-collectors |
412 | | - (asynchronousWikipediaArticleObservable ["Atom" "Molecule"]) |
413 | | - 5000) |
414 | | - :onNext) |
415 | | - (map #(html/select % [:title])) |
416 | | - )) |
| 448 | +(->> |
| 449 | + ((subscribe-collectors |
| 450 | + (asynchronousWikipediaArticleObservable ["Atom" "Molecule"]) |
| 451 | + 5000) |
| 452 | + :onNext) |
| 453 | + (map #(html/select % [:title])) |
| 454 | + (pdump)) |
417 | 455 |
|
418 | 456 | (pdump (+ 4 3)) |
0 commit comments