2011-09-07

Zipping With Arrays in RxJs

Have you ever tried to zip a hot observable with a cold one? That's what happens below.
   var former = function(a, b) { return a }
   var latter = function(a, b) { return b }
   var logger = function(a) { console.log(a) }
   var numbers = Rx.Observable.FromArray([1, 2, 3])
   var timer = Rx.Observable.Interval(100)
   var zipped = numbers.Zip(timer, former)
   zipped.Subscribe(logger)
The idea is to print out the contents of an array to the console one-by-one, each 100 milliseconds. It doesn't work though. What I've heard is that it fails because of a bug in Rx. Instead of printing out numbers 1,2,3 to the console, the code does ... nothing.
A simple workaround (Thanks Jussi) seems to work, though: Just concat your array observable with Rx.Observable.Never!
   // ...
   numbers.Concat(Rx.Observable.Never()).Zip(timer, former).Subscribe(logger)

1
2
3

So, now it prints the stuff to the console as you'd expect.
To make zipping with arrays a bit easier, you could add a ZipWithArray method to the Observable prototype like this.
  Rx.Observable.prototype.ZipWithArray = function(array, selector) {·
      return this.Zip(Rx.Observable.FromArray(array).Concat(Rx.Observable.Never()), 
  }
I've put this extension, as well a bunch of others on Github, in my rxjs-extensions project.

2011-09-06

A Nice Java HashMap Antipattern


Don't you just love how simple it is to instantiate maps in Java? Like, could it be any uglier than
Map<String, String> map = new HashMap<String, String>();
map.put("fruit", "banana");
map.put("vegetable", "carrot");
I saw someone using a pattern that made it look a bit nicer, like
Map<String, String> map = new HashMap<String, String>() {
  put("fruit", "banana");
  put("vegetable", "carrot");
}
It kinda puts a bit more structure to this mess. However, you'll get some unwanted runtime side-effects.
When you use this "syntax", you'll actually create a new anonymous inner class. Each anonymous inner class instace will have a runtime reference to thethis object for the context where you define the anonymous inner class in. Thus, if your this happens to have references to 100 megabytes of porn, that stuff will not be GC'd as long as this Map or yours is alive. Also, should you try to serialize your map for sending or storing it somewhere, you'll also be sending your 100 megabytes of porn.
Enjoy your cup of Java!