Was implementing reactive streams for Lispz worth the effort? Let’s see where we stand. Let’s consider the example from the last blog post.
(using [message] (cascade (=> (dom.click "my-message-address" document.body)) (=> (message.map @ "mouse" (=> {x: @.clientX y: @.clientY}))) (=> (message.filter @ "top-left" (=> (< @.x @.y)))) (=> (message.throttle @ 2000)) (=> (message.listen @ (=> (console.log @.x @.y)))) ) )
If we did not have message streams, the code would look something like:
(document.body.addEventListener "click" (lambda [event] (ref data (stateful { last-time: 0 })) (ref loc { x: event.clientX, y: event.clientY }) (cond (< loc.x loc.y) (do (ref now (Date)) (cond ((> data.last-time (+ now 2000))) (data.update! { last-time: now }) (console.log loc.x loc.y) ) )) ))
Well, I guess that answers that. Reactive streams are a lot more readable than in-line code. In addition you are not rewriting throttle every time you need it.
Perhaps I should have asked the question “When don’t we use Reactive Streams for asynchronous events“.
- When a promise will do – so any server request that does not need to send a message.
- When a stream will have more than one source, or wait on a promise. The current architecture doesn’t merge asynchronous events (yet).
Ok, that is a shorter list thank I expected. Can you think of others? It seems to me that streams work well for continuous discrete data flows from callbacks and events.