EventStream and Future functors
EventStream
- An infinite list of results
- Dual of array
- Its map is sometimes lazy
- Calls the mapped function each time an event happens
It's like composing addEventlisteners
. We map over all the events then.
Note: reminds me of RxJS.
// uses BaconJS...
var id_s = map(function(e) { retunr '#'+e.id }, Bacon.fromEventTarget(document, 'click'))
// => EventStream(String)
id_s.onValue(function(id){ alert('you clicked' + id) })
In fact he mentions that BaconJS and RxJS are very similar...
With streams we get a tangible object that we can map
over. It's all lazy. Itt will only kick off when we run id_s.onValue(..)
. This will start the event listener.
var id_s = map(function(e) { retunr '#'+e.id }, Bacon.fromEventTarget(document, 'click'))
var element_s = map(document.querySelector, id_s)
// => EventStream(Element)
id_s.onValue(function(el){ alert('The inner HTML is' + el.innerHTML) })
Notice that here we're mapping twice over the stream object. First get the #id then the querySelector
.
var hover_s = Bacon.fromEventTarget(document, 'hover')
var element_s = map(compose(document.querySelector, get('id')), hover_s)
var postid_s = map(function(el) { return el.data('post-id')}, element_s)
var future_post_s = map(Api.getProductById, postid_s)
// => EventStream(Future(Post))
// nothing happens until I call
future_post_s.onValue(alert)
An example that we can keep transforming (map
ing) the event stream objects.
This is the reactive stuff. This is all lazy stuff until I call
future_post_s.onValue(alert)
What about the future
prefix above?
Future
- Has an eventual value
- Similar to a promise, but it's "lazy"
- You must
fork
it to kick it off - It takes a functor as it's value
- Calls the function with it's result once it's there
It's got IO
rolled into it. (only when you have a long running calculation when you don't have an io in it.)
var makeHtml = function (post) { return '<div>' + post.title + '</div' }
var page_f = map(makeHtml, http.get('/posts/2'))
page_f.fork(
function (err) { throw err}),
function(page) { $('#container').html(page) }
)
This is an alternative to callbacks. Or it's just like then
on a Promise. We map
the value over the eventual value.
My note: map
works like compose here. It maps the result of http.get(..)
(that returns a future) to makeHtml
which is just a simple function. Or to be more precise: map
is a curried function. So before we were always taking advantage that it was curried, so now, in the original form, calling it with both arguments at the same time now looks novel.
about .fork
: all the apps will follow this pattern. First value is the error branch, then the success branch.
Futures will fail, so they've rolled io
and maybe
into one functor. It's all lazy.
var makeHtml = function (title) { return '<div>' + title + '</div' }
var createPage = compose(makeHtml, get('title'))
var page_f = compose(map(createPage), http.get('/posts/2'))
page_f.fork(
function (err) { throw err}),
function(page) { $('#container').html(page) }
)
Note: http.get(...)
will return a future. But it would have been to complex to show that part here...
In your day to day work, the library will return you a future, so you will not have to be making them all the time.
var lineCount = compose(length, split(/\n/))
var fileLineCount = compose(map(lineCount), readFile)
fileLineCount('mydoc.txt').fork(log, log)
=> 34
This pattern is great in NodeJS, where everything is asynchronous. This solves the callback hell.
Is there a Promise or functor library for NodeJS that does this?
He doesn't say the name, but that it would be the same as a Promise library, except that you have to run it at the end to kick it off.