EventStream and Future functors

In notebook:
FrontEndMasters Hardcore Functional
Created at:
2017-06-05
Updated:
2019-08-15
Tags:
Functional Programming JavaScript libraries React

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 (maping) 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

http://jsbin.com/yikoqi

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.