I've got trouble wrapping my head around a certain problem:
In my data-flow app (a visual editor), I have both autonomous objects which communicate though ports via unordered simultaneous messages and thus represent an asynchronous system.
Still, I also want to use functions which are synchronous, e.g they need input to compute it's value
Now the problem is – how do I combine both with a non-trivial system?
In this picture, f needs x and y to compute its value, but during any point in time, only one input may be present (suppose x is present, y is not). Generalize this to higher dimensions
I can see a possible way out:
-
make x an array X = (x,y) and combine the first two objects resulting
in a Type-1 like system .. -
or make f an active object, which caches x,y and then computes
-
or make f always compute its value (e.g when only x is present, compute x*y = x*0 …)
So the possibility of futures was mentioned. I'M using Java, so i'll frame my possible solution via Objects
X is sent, y is missing -> create future (maybe a copy of f) waiting for y
Best Answer
Promises were made to solve problems like this; they work really well in functional languages (I've personally used them extensively in Javascript, where curiously jQuery actually has the worst implementation of them - see this comparison). The weird thing about using promises is accepting that things are easier when you make everything use them. I will frame my answer in JavaScript terms using the promise library Q, since that's what I know best - apologies if that's not your cup o' tea, and double apologies for answering a language agnostic question with a specific language and library to boot.
A promise is a wrapper for a callback function. In many libraries, this is called a
.then()
function. In simplest terms, a promise waits for a return, and then calls the function passed tothen()
. The simplicity was confusing for me in the beginning, so lets use your example. Let me upgradex
andy
to functions. If they are functions that return promises (as many asynch heavy libraries do, like a NodeJS database accessor), this becomes trivial.The trouble is, what if
x()
andy()
don't return promises? As I mentioned, your life gets easier if you make them return promises. Fortunately, any half-decent promise library provides tools for this as well. In fact, there are several ways to do this in Q.If you repeat that code for the
y()
function, you get back to where you can useQ.all()
to wait for bothx()
andy()
to complete.Q also provides an API for creating promises, which is like a wrapper function for
Q.defer()
.However, the best feature a promise library provides is aggregated error handling. Expanding on our first
Q.all
example, what happens if x or y throw an error? As that code is written now, it gets lost. Consider the following:You'll also notice in the above example there are several places where combining sync and async methods is demonstrated.
Ultimately, the tools that are at your disposal depend upon your language and environment. Promises have been implemented in more languages than just JS, and another closely related idiom from async/functional programming is Futures. Admittedly, if your language of choice does not have a Promise library, this answer will be pretty useless to you, but hopefully you at least find it interesting.
Update: Now that you mention Java, it looks like there is a decent promise library in JDefered. I've not used it, but it looks like my examples could be applied with it in a fairly straightforward manner.