Hacker News new | ask | show | jobs
by rybosome 4446 days ago
I haven't done any serious FRP, but thinking about your example of the drag adapter, wouldn't it be possible to do something like the following?

  - Declare a stream consisting of the composite of two stream: a mouse down and a mouse up
  - Map over the mouse down portion, transforming into an (x, y) coordinate
  - Map over the mouse up portion, transforming into an (x, y) coordinate
  - Produce a tuple of the two values
  - Use the resulting signal that determines what to do with the drag
In Bacon.js, I think it would look something like this (haven't tested it):

  var makeCoordinate = function(v) { return {x: v.clientX, y: v.clientY}; }
  var mergeStreams = function(v1, v2) { return {down: makeCoordinate(v1), up: makeCoordinate(v2)}; };

  var $html = $('html');
  var mousedownStream = $html.asEventStream('mousedown');
  var mouseupStream = $html.asEventStream('mouseup');
  var dragStream = mousedownStream.flatMap(function() {
    // Ensure that we only sample a single mousedown/mouseup pair.
    return Bacon.zipWith([mousedownStream, mouseupStream], mergeStreams).
        takeUntil(mouseupStream);
  };
I don't mean to be pedantic - your point is well taken. This was definitely a mental exercise to write, and I have no experience debugging (though I imagine it would be difficult).

EDIT: For this particular example I actually made it more complicated than it needs to be. Example JS Fiddle here: http://jsfiddle.net/w6mCK/

1 comments

Compare with the control flow heavy managed time [1] version:

  on widget.Mouse.Down:
  | var pw = widget.position
  | var pm = widget.Mouse.Position
  after:
  | widget.Mouse.Capture()
  | widget.position = pw + (widget.Mouse.Position - pm)
  | on widget.Mouse.Up:
  | | widget.position = widget.position # freeze widget position
  | | break                             # stop the after block so capture/dragging stops
[1] http://research.microsoft.com/pubs/211297/managedtime.pdf