a-synchronous / rubico

[a]synchronous functional programming
https://rubico.land
MIT License
275 stars 15 forks source link

How do we deal with short-circuit in pipelines using Rubico? #191

Closed thelinuxlich closed 2 years ago

richytong commented 3 years ago

You could throw errors in pipelines wrapped with tryCatch to shortcircuit.

tryCatch(pipe([
  doSomething,
  doSomethingElse,
  tap(function shortCircuitByThrowing() {
    if (someTrueCondition) {
      throw new Error('I will effectively shortcircuit this pipeline')
    }
  }),
  someFuncThatIsNotReachedBecauseOfShortCircuiting,
]), error => {
  console.log('caught error:', error.message) // caught error: I will effectively shortcircuit this pipeline
})(...args)
thelinuxlich commented 3 years ago

the intention wasn't to throw errors, but to keep going like Railway Oriented Programming: https://fsharpforfunandprofit.com/rop/

I see libraries like Sanctuary doing that transparently using Maybe

richytong commented 3 years ago

If you'd like to use the Maybe monad, it is possible with rubico, you would just need to explicitly use flatMap on the monadic value

pipe([
  Maybe,
  flatMap(myFunc),
  flatMap(myOtherFunc),
])(myValue)

and a quick Maybe monad implementation

function Maybe(value) {
  return {
    value,
    flatMap(func) { // chain works here as well
      return Maybe(value == null ? value : func(value))
    },
  }
}

maybe we could think about a special version of pipe to make this syntax look less clunky? Maybe pipe.chain

pipe.chain([
  myFunc,
  myOtherFunc,
])(Maybe(myValue))
thelinuxlich commented 3 years ago

I think this is a good example from the Sanctuary introductory video: https://youtu.be/a2astdDbOjk?t=1157

thelinuxlich commented 3 years ago

But I agree pipe.chain might be the right direction