|
7 | 7 | rest seq some sort sort-by split-with
|
8 | 8 | take take-while throw])
|
9 | 9 | (:require [rx.lang.clojure.interop :as iop]
|
10 |
| - [rx.lang.clojure.base :as base] |
11 | 10 | [rx.lang.clojure.graph :as graph]
|
12 | 11 | [rx.lang.clojure.realized :as realized])
|
13 | 12 | (:import [rx Observable Observer Subscriber Subscription Observable$Operator Observable$OnSubscribe]
|
|
156 | 155 |
|
157 | 156 | ;################################################################################
|
158 | 157 |
|
| 158 | +(defn wrap-on-completed |
| 159 | + "Wrap handler with code that automaticaly calls rx.Observable.onCompleted." |
| 160 | + [handler] |
| 161 | + (fn [^Observer observer] |
| 162 | + (handler observer) |
| 163 | + (.onCompleted observer))) |
| 164 | + |
| 165 | +(defn wrap-on-error |
| 166 | + "Wrap handler with code that automaticaly calls (on-error) if an exception is thrown" |
| 167 | + [handler] |
| 168 | + (fn [^Observer observer] |
| 169 | + (try |
| 170 | + (handler observer) |
| 171 | + (catch Throwable e |
| 172 | + (.onError observer e))))) |
| 173 | + |
| 174 | +(defn ^Observable merge |
| 175 | + "Observable.merge, renamed because merge means something else in Clojure |
| 176 | +
|
| 177 | + os is one of: |
| 178 | +
|
| 179 | + * An Iterable of Observables to merge |
| 180 | + * An Observable<Observable<T>> to merge |
| 181 | +
|
| 182 | + If you want clojure.core/merge, it's just this: |
| 183 | +
|
| 184 | + (rx/reduce clojure.core/merge {} maps) |
| 185 | +
|
| 186 | + " |
| 187 | + [os] |
| 188 | + (cond |
| 189 | + (instance? Iterable os) |
| 190 | + (Observable/merge (Observable/from ^Iterable os)) |
| 191 | + (instance? Observable os) |
| 192 | + (Observable/merge ^Observable os) |
| 193 | + :else |
| 194 | + (throw (IllegalArgumentException. (str "Don't know how to merge " (type os)))))) |
| 195 | + |
| 196 | +(defn ^Observable merge-delay-error |
| 197 | + "Observable.mergeDelayError, renamed because merge means something else in Clojure" |
| 198 | + [os] |
| 199 | + (cond |
| 200 | + (instance? java.util.List os) |
| 201 | + (Observable/mergeDelayError ^java.util.List os) |
| 202 | + (instance? Observable os) |
| 203 | + (Observable/mergeDelayError ^Observable os) |
| 204 | + :else |
| 205 | + (throw (IllegalArgumentException. (str "Don't know how to merge " (type os)))))) |
| 206 | + |
| 207 | +(defn ^Observable zip |
| 208 | + "Observable.zip. You want map." |
| 209 | + ([f ^Observable a ^Observable b] (Observable/zip a b (iop/fn* f))) |
| 210 | + ([f ^Observable a ^Observable b ^Observable c] (Observable/zip a b c (iop/fn* f))) |
| 211 | + ([f ^Observable a ^Observable b ^Observable c ^Observable d] (Observable/zip a b c d (iop/fn* f))) |
| 212 | + ([f a b c d & more] |
| 213 | + ; recurse on more and then pull everything together with 4 parameter version |
| 214 | + (zip (fn [a b c more-value] |
| 215 | + (apply f a b c more-value)) |
| 216 | + a |
| 217 | + b |
| 218 | + c |
| 219 | + (apply zip vector d more)))) |
| 220 | + |
| 221 | +(defmacro zip-let |
| 222 | + [bindings & body] |
| 223 | + (let [pairs (clojure.core/partition 2 bindings) |
| 224 | + names (clojure.core/mapv clojure.core/first pairs) |
| 225 | + values (clojure.core/map second pairs)] |
| 226 | + `(zip (fn ~names ~@body) ~@values))) |
| 227 | +;################################################################################ |
| 228 | + |
| 229 | + |
| 230 | + |
| 231 | + |
| 232 | + |
159 | 233 | (defn ^Observable never [] (Observable/never))
|
160 | 234 | (defn ^Observable empty [] (Observable/empty))
|
161 | 235 |
|
|
288 | 362 | "Map a function over an observable sequence. Unlike clojure.core/map, only supports up
|
289 | 363 | to 4 simultaneous source sequences at the moment."
|
290 | 364 | ([f ^Observable xs] (.map xs (iop/fn* f)))
|
291 |
| - ([f xs & observables] (apply base/zip f xs observables))) |
| 365 | + ([f xs & observables] (apply zip f xs observables))) |
292 | 366 |
|
293 | 367 | (defn ^Observable mapcat
|
294 | 368 | "Returns an observable which, for each value x in xs, calls (f x), which must
|
|
317 | 391 | (fn [o v] (on-next o (f (swap! n inc) v)))))))]
|
318 | 392 | (lift op xs)))
|
319 | 393 |
|
320 |
| -; TODO which merge goes here? |
321 |
| -(defn merge |
322 |
| - " |
323 |
| - Returns an observable that emits a single map that consists of the rest of the |
324 |
| - maps emitted by the input observable conj-ed onto the first. If a key occurs |
325 |
| - in more than one map, the mapping from the latter (left-to-right) will be the |
326 |
| - mapping in the result. |
327 |
| -
|
328 |
| - NOTE: This is very different from rx.Observable/merge. See rx.base/merge for that |
329 |
| - one. |
330 |
| -
|
331 |
| - See: |
332 |
| - clojure.core/merge |
333 |
| - " |
334 |
| - [maps] |
335 |
| - (reduce clojure.core/merge {} maps)) |
336 |
| - |
337 | 394 | (def next
|
338 | 395 | "Returns an observable that emits all but the first element of the input observable.
|
339 | 396 |
|
|
545 | 602 | "
|
546 | 603 | [f & args]
|
547 | 604 | (fn->o (-> #(apply f % args)
|
548 |
| - base/wrap-on-completed |
549 |
| - base/wrap-on-error))) |
| 605 | + wrap-on-completed |
| 606 | + wrap-on-error))) |
550 | 607 |
|
551 | 608 | (defmacro generator
|
552 | 609 | "Create an observable that executes body which should emit a sequence. bindings
|
|
0 commit comments