Saturday, April 24, 2010

Can I transform this asynchronous java network API into a monadic representation (or something else idiomatic)?

Programmer Question

I've been given a java api for connecting to and communicating over a proprietary bus using a callback based style. I'm currently implementing a proof-of-concept application in scala, and I'm trying to work out how I might produce a slightly more idiomatic scala interface.



A typical (simplified) application might look something like this in Java:



    DataType type = new DataType();
BusConnector con = new BusConnector();
con.waitForData(type.getClass()).addListener(new IListener<DataType>() {
public void onEvent(DataType t) {
//some stuff happens in here, and then we need some more data
con.waitForData(anotherType.getClass()).addListener(new IListener<anotherType>() {
public void onEvent(anotherType t) {
//we do more stuff in here, and so on
}
});
}
});

//now we've got the behaviours set up we call
con.start();


In scala I can obviously define an implicit conversion from (T => Unit) into an IListener, which certainly makes things a bit simpler to read:



implicit def func2Ilistener[T](f: (T => Unit)) : IListener[T] = new IListener[T]{
def onEvent(t:T) = f
}

val con = new BusConnector
con.waitForData(DataType.getClass).addListener( (d:DataType) => {
//some stuff, then another wait for stuff
con.waitForData(OtherType.getClass).addListener( (o:OtherType) => {
//etc
})
})


Looking at this reminded me of both scalaz promises and f# async workflows.



My question is this:



Can I convert this into either a for comprehension or something similarly idiomatic (I feel like this should map to actors reasonably well too)



Ideally I'd like to see something like:



for(
d <- con.waitForData(DataType.getClass);
val _ = doSomethingWith(d);
o <- con.waitForData(OtherType.getClass)
//etc
)


Find the answer here

No comments:

Post a Comment

LinkWithin

Related Posts with Thumbnails