ramda: pipeP fails when first argument is function that does not return promise

This seems like obviously pathological behavior. Tested on version 0.18.0.

var R = require("ramda")
var Promise = require("bluebird")

var mulslow = R.curry(function (x, y) {
    return new Promise(function (resolve, reject) {
        resolve(x * y)
    })
})

R.pipeP(mulslow(3))(3).then(console.log) // works
R.pipeP(mulslow(3),R.multiply(3))(3).then(console.log) // works
R.pipeP(mulslow(3),R.multiply(3),mulslow(3))(3).then(console.log) // works
R.pipeP(R.multiply(3), mulslow(3))(3).then(console.log).catch(console.log) // does not work.
R.pipeP(R.multiply(3))(3).then(console.log).catch(console.log) // does not work.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 20 (12 by maintainers)

Most upvoted comments

That function seems reasonable to me, @Zerim.

I think I’ve almost convinced @CrossEye that we should deprecate our Promise-specific functions, so I don’t expect R.composeP to be “fixed”.

There are a few issues here:

  • If we don’t require the first function to return a valid Promise, there is a possibility that none of the functions given to pipeP will return a Promise, meaning that pipeP as a whole won’t return a Promise which makes for inconsistent return types.
  • We can avoid this by calling Promise.resolve on the output of the first function if it is missing a then method, however this then adds a dependency on a Promise implementation.
  • We can work around this by hand-rolling our own minimal Promise implementation, but we’re then hand-rolling our own Promise implementation.

This can however be avoided currently by users starting the pipeP composition with the appropriate function from the Promise implementation that lifts plain values into a Promise instance. This is only necessary if the first function would otherwise not return a Promise.

e.g. for ES6 Promises:

R.pipeP(Promise.resolve, R.add(42), someOtherAsyncFn);
// or if the pipeline needs to accept multiple arguments
R.pipeP(R.compose(Promise.resolve, R.add), someOtherAsyncFn);