Open brian-gates opened 9 years ago
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.
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.