wrapCallback is uncurryable
var foo = _.wrapCallback(function (thing, done){
done(null, thing);
});
foo('bar').apply(_.log); // bar
_.curry(foo)('bar').apply(_.log);
// ^
// TypeError: object is not a function
The issue is that wrapCallback handles its arguments dynamically. I'm not sure there's any way around it, but I wanted to raise it for discussion as it would be a useful thing to be able to do. I suppose _.partial could be used instead, but that's less elegant.
// _.wrapCallback
function () {
var self = this;
var args = slice.call(arguments);
return _(function (push) {
var cb = function (err, x) {
if (err) {
push(err);
}
else {
push(null, x);
}
push(null, nil);
};
f.apply(self, args.concat([cb]));
});
}
There's not really a solution for this. The only way of creating a function of a given arity at runtime is the Function constructor, which would have a huge performance impact.
A workaround would be to use _.ncurry with the expected length of the function:
var foo = _.wrapCallback(function (thing, done){
done(null, thing);
});
foo('bar').apply(_.log); // bar
_.ncurry(2, foo)('bar').apply(_.log);
I suppose we could have wrapCallback save the original function length as a separate property (length isn't writable) that curry could then use, but that only solves this particular case.
What if we curried by default? Seems within the spirit of this lib.
var wrapCallback = function (f) {
return _.ncurry(f.length-1, function () {
var self = this;
var args = slice.call(arguments);
return _(function (push) {
var cb = function (err, x) {
if (err) {
push(err);
}
else {
push(null, x);
}
push(null, nil);
};
f.apply(self, args.concat([cb]));
});
});
};
var foo = wrapCallback(function (thing, thing2, done){
done(null, [thing, thing2]);
});
foo('bar')('baz').apply(_.log); // [ 'bar', 'baz' ]
We can't, because the function being wrapped might have varargs. It's not in our control.
The only reasonable solution besides using ncurry is to have ncurry embed the length information in curried functions, which wrapCallback can use. So you can do something like this
var foo = _.wrapCallback(_.curry(function (thing1, thing2, done) {
done(null, [thing1, thing2]);
}));
foo('bar')('baz').apply(_.log);
This essentially saves you from having to figure out the length of wrapped functions that aren't varargs (lets you use curry instead of ncurry). But it'll only work on highland-curried functions. The semantics would be: curried function -> curried function out.
Good point about varargs.
Curried in -> curried out seems sensible enough to me.