I have been playing around with the pipe operator and RxJS, but I quickly ran into issues
on the binding side. As you might know an operator in RxJS is just a function that takes an observable and returns an observable:
let operator: observable<'a> => observable<'b>
But since we often need extra parameters to know how to build these observable, all RxJS operators
are wrapped with an extra function taking additional parameters:
let map: ('a => 'b) => observable<'a> => observable<'b>
If we were to uncurry that, it looks just like a data last function:
let map: ('a => 'b, observable<'a>) => observable<'b>
Having the data last makes a lot of sense in the RxJS library, since it is used with the .pipe
function in JS (having the data first wouldn’t work with this pattern):
from([1, 2, 3])
.pipe(map(number => number + 1))
.subscribe(number => console.log(number));
This brings me to the actual question. Is it possible to make bindings to these operators so they
can be used with the data first pipe operator? Currently I’m doing something like this, which works
fine, but generates a lot of extra code:
type observable<'a>
type operator<'a, 'b> = observable<'a> => observable<'b>;
@module("rxjs/operators")
external _mapOperator: ('a => 'b) => operator<'a, 'b> = "map"
let map = (source, project) => _mapOperator(project)(source)
And then I only use the map function. Complete example:
type observable<'a>
type operator<'a, 'b> = observable<'a> => observable<'b>;
type subscription
@send
external subscribe: (observable<'a>, 'a => unit) => subscription = "subscribe"
@module("rxjs")
external fromArray: array<'a> => observable<'a> = "from"
@module("rxjs/operators")
external _mapOperator: ('a => 'b) => operator<'a, 'b> = "map"
let map = (source, project) => _mapOperator(project)(source)
let sub = fromArray([1, 2, 3])
->map(number => number + 1)
->subscribe(number => Js.log(number)) // Logs 2, 3, 4
This also works and generates less code, but IMO looks pretty bad with the placeholder syntax:
@module("rxjs/operators")
external map: ('a => 'b, . observable<'a>) => observable<'b> = "map"
let obs = fromArray([1, 2, 3])
->map(number => number + 1)(. _)
->subscribe(number => Js.log(number))