官术网_书友最值得收藏!

Manipulating observables

Now that we know how to create observables, we should look at what kinds of interesting things we can do with them. In this section, we will see what it means to treat observables as sequences.

We'll start with something simple. Let's print the sum of the first five positive even integers from an observable of all integers:

(rx/subscribe (->> (Observable/interval 1 TimeUnit/MICROSECONDS) 
                   (rx/filter even?) 
                   (rx/take 5) 
                   (rx/reduce +)) 
                   prn-to-repl) 

This is starting to look awfully familiar to us. We create an interval that will emit all positive integers starting at zero every one microsecond. Then, we filter all even numbers in this observable. Obviously, this is too big a list to handle, so we simply take the first five elements from it. Finally, we reduce the value using +. The result is 20.

To drive home the point that programming with observables really is just like operating on sequences, we will look at one more example, where we will combine two different observable sequences. One contains the names of musicians I'm a fan of and the other the names of their respective bands:

(defn musicians [] 
  (rx/seq->o ["James Hetfield" "Dave Mustaine" "Kerry King"])) 
 
(defn bands     [] 
  (rx/seq->o ["Metallica" "Megadeth" "Slayer"])) 

We would like to print to a string of the format Musician name - from: band name to the REPL. An added requirement is that the band names should be printed in uppercase for impact.

We'll start by creating another observable that contains the uppercased band names:

(defn uppercased-obs [] 
  (rx/map (fn [s] (.toUpperCase s)) (bands))) 

While not strictly necessary, this makes a reusable piece of code that can be handy in several places of the program, thus avoiding duplication. Subscribers interested in the original band names can keep subscribing to the bands observable.

With the two observables in hand, we can proceed to combine them:

(-> (rx/map vector 
            (musicians) 
            (uppercased-obs)) 
    (rx/subscribe (fn [[musician band]] 
                    (prn-to-repl (str musician " - from: " band))))) 

Once more, this example should feel familiar. The solution we were after was a way to zip the two observables together. RxClojure provides zip behavior through map, much like Clojure's core map function does. We call it with three arguments: the two observables to zip and a function that will be called with both elements, one from each observable, which should return an appropriate representation. In this case, we simply turn them into a vector.

Next, in our subscriber, we simply destructure the vector so that we can access the musician and band names. Finally, we can print the final result to the REPL:

    "James Hetfield - from: METALLICA"
    "Dave Mustaine - from: MEGADETH"
    "Kerry King - from: SLAYER"  
主站蜘蛛池模板: 全南县| 宁津县| 上犹县| 湄潭县| 桦川县| 水城县| 泊头市| 施甸县| 贵南县| 罗源县| 阿克苏市| 准格尔旗| 安平县| 正安县| 夏河县| 连平县| 韶关市| 宕昌县| 马边| 宽甸| 霸州市| 修水县| 海城市| 自治县| 徐州市| 郓城县| 上林县| 湖南省| 泰兴市| 滕州市| 冕宁县| 武汉市| 肇州县| 肥乡县| 洪泽县| 乌兰浩特市| 闻喜县| 洱源县| 泉州市| 峡江县| 霍林郭勒市|