baconjs / bacon.js

Functional reactive programming library for TypeScript and JavaScript
https://baconjs.github.io
MIT License
6.47k stars 330 forks source link

Bacon.js observable.bind #281

Closed phadej closed 10 years ago

phadej commented 10 years ago

As per in the stackoverlflow question there is no such functionality as auto-catching exceptions inside Bacon.

I guess, catching exceptions inside Bacon, would ruin lazyness, so maybe Observable.bind (or some other less Haskell inspired name) would be enough. This would be something in between of withHandler and map:

property.bind(function (value) {
  if (value < 0) {
    return new Bacon.Error("negative value");
  } else {
    return Math.sqrt(value);
  }
});

And additionally some Bacon wrapper for exception throwing functions:

someUnsafeInput.bind(Bacon.safe(JSON.parse)).onValue( //...
raimohanska commented 10 years ago

That's a good idea. I'll give this a bit more thought later, hopefully soon.

raimohanska commented 10 years ago

Actually, there already is a function that does a monadic bind, i.e. flatMap. So in fact you can do

stream = Bacon.fromArray([1,2,3,4]).flatMap (x) ->
  if (x > 2)
    Bacon.once(new Bacon.Error("too big"))
  else
    Bacon.once(x)

Using this, you could implement the rest. But what should the error-catching API look like as a whole?

phadej commented 10 years ago

Ah true, missed flatMap from the documentation completely. With:

  function tryWrap(f) {
    return function (value) {
      try {
        return Bacon.once(f(value));
      } catch (err) {
        return Bacon.once(new Bacon.Error(err));
      }
    };
  }

you can do

var $obj = objInput.flatMap(tryWrap(JSON.parse));

Maybe you can name tryWrap Bacon.Try, if you like scala names :)

raimohanska commented 10 years ago

Oh and indeed, flatMap allows you to return values and Error object directly without wrapping them into streams, like this:

stream = Bacon.fromArray([1,2,3,4]).flatMap (x) ->
  if (x > 2)
    new Bacon.Error("too big")
  else
    x
raimohanska commented 10 years ago

TODO: documentation for using flatMap like this. Wiki? Readme?

phadej commented 10 years ago

I guess a type signature for flatMap (and why not others functions as well) could be valuable (for advanced users). If I understood correctly (I'm not sure about order of different overloadings, or Value[B] name), for flatMap type signature is:

Observable[A].flatMap (f : A => Observable[B] | Value[B] | B) : Observable[B]

Someone with Haskell / Scala background (like me) could think that f must always return Observable[B]. It's also hard to cover everything with examples.

The fact that Bacon.Observable is something like List[Either[E, A]] wasn't crystal clear. It might be worth pointing to people with scala+rxjava background, that Bacon.Observable isn't List[Try[A]] as it doesn't catch exceptions.

raimohanska commented 10 years ago

1) I'd love to have type signatures. Not just for advanced users but for anyone with a taste for types. Not sure where to place them in the documentation though. They'd certainly look bad on the current Readme. Which brings me back to the original issue with documentation: A more structured API doc (than the Readme) would be nice. I've dreamed about a site with a structured API doc including type signatures, (live?) examples etc. I wish someone paid me to work a couple of days on the docs :)

2) From a staticly typed perpective it for sure is a bit strange that you can return different types of objects from f. But in Javascript, this is how we do stuff, don't we? Still, I've tried to err on the safe side, by, for example, not using concepts like "thenable" where pure values are separated from Promises just by the existence of a certain method in the object.

Oh, and a blog posting covering Bacon.js from a Scala/RxJava perspective might be in order, nudge nudge.

phadej commented 10 years ago

Single page documentation is a must. Bacon is quite small and simple library after all. We just need to have clever navigation on that page.

I guess API references extracted from source file would be a great start. I don't know how codo approach would work for bacon.js. I personally like more freeform, literate approach (like https://github.com/phadej/grunt-literate, but that's for javascript), so you can introduce needed structure freely (and lazily, on need). I also hate javadoc style tags and javadoc look'n'feel of the generated docs.

Of course there is docco, but you can't really introduce any additional structure with it.

I'd like to help with the documentation, even it would require writing yet-another-documentation-generation tool.

raimohanska commented 10 years ago

I'm not sure about generating docs from the actual code, because then the code size will go 10x and will be harder for me to maintain. However, it would be preferable to have a single place for maintaining the docs with possibly multiple output formats

We could of course use a doc generator even if we don't use it on the actual coffeescript source code.

So, if you have ideas for improving the single page API doc (readme) pls show us! For example, a generator-based example of a subset of the whole API would be great.

raimohanska commented 10 years ago

I added the flatMap example to readme.

Closing this one.