But – A way to pass along a callback with just a single argument
github.com
github.com
var butt = require('butt');
var but = function(fun) {
return butt(fun, 1);
};
or even var but = function(fun) {
return function(arg) {
return fun(arg);
};
}; module.exports = function (fn) {
return function (first) {
fn(first);
};
}; n.forEach(console.log);
Just tested on Chrome, it gives me an error TypeError: Illegal invocation n.forEach(console.log.bind(console));
I don't think there's any reason for this library to exist after you understand `this` semantics but I may be missing something.e: was, in fact, missing something. Apologies for the disparaging comment, see replies.
n.forEach(console.log.bind(console));
forEach is passing console all of its callback arguments, resulting in logging of keys, values, and array.EDIT: Forgot array
[1, 2, 3].forEach(console.log.bind(console));
> 1 0 [1, 2, 3]
> 2 1 [1, 2, 3]
> 3 2 [1, 2, 3] n.forEach(console.log);
Works on firefox. Chrome treats console.log differently from other functions for reasons unknown.but really, this library has no reason to exist
function butter (){
fn=arguments[0];
return function(){
var args = [];
for( var n=1; n<arguments.length; n++ ) {
args.push(arguments[n]);
};
return fn.apply(this,args)
}
}
edit: I know my loop is totally anachronistic, but I'm short on time for testing this. function butter(fun, count) {
count = count || 1;
if (count < 1) {
throw new Error('Can't butter no toast');
}
return function() {
return fun.apply(this, Array.prototype.slice.call(arguments, 0, count));
}
}The reason why it's necessary to specify how many arguments are of interest is because
Of course, since this is just common or garden partial application in a language with first-class functions and a liberal attitude toward signatures, it could be trivially generalized thus:
function partial(fun) {
var applied = Array.prototype.slice.call(arguments, 1);
return function() {
var args = applied
// clone the already applied args, so we don't mistakenly modify when we...
.slice()
// ...tack on the args we received in this function's call
.concat(Array.prototype.slice.call(arguments));
return fun.apply(this, args);
};
}
var addThreeNumbers = function(a, b, c) {
return a + b + c;
};
var onePlusTheseTwo = partial(addThreeNumbers, 1);
var threePlusThisOne = partial(onePlusTheseTwo, 2);
assert(addThreeNumbers(1, 2, 3) === 6);
assert(onePlusTheseTwo(2, 3) === 6);
assert(threePlusThisOne(3) === 6);
// -> all true
It only looks like wizardry if you're not used to dealing with higher-order functions, wherein I think is meant to lie the joke, if any.What I was having trouble understanding was why it was being used; specifically, why 'but' would have a strict arity of one in the first place, and why a second function (specifying arity) would be necessary. It doesn't follow very clearly from the examples given at all.
edit: ...was this whole thing actually a joke? I thought he was serious.
See, you can't just
['1', '2', '3'].map(parseInt)
because:0) All Javascript functions are variadic; the signature specified at definition time is largely advisory, and has semantic meaning only in that the language will automatically declare and bind named arguments. Arguments named in a function's signature, but not passed at call time, are undefined; arguments not named in a function's signature, but passed at call time, are not automatically bound to named variables, but can be accessed via the arguments binding, which is a unique object magically bound within a function's scope, but which will be overridden by a named argument "arguments" if one exists in the signature,
and
1) Array.map and friends pass their callbacks three arguments: the value of the element, the index of the element in the array being mapped over, and a reference to the entire array being mapped over,
and
2) Number.parseInt requires one argument, the value to cast to integer, and accepts an optional second argument, specifying a radix between 2 and 36 inclusive.
So our naïve mapping above expands to the following series of calls:
parseInt('1', 0, ['1', '2', '3']);
// -> 1
parseInt('2', 1, ['1', '2', '3']);
// -> NaN
parseInt('3', 2, ['1', '2', '3']);
// -> NaN
tl;dr: None of this would be necessary in a language whose collection methods did sane things. Since Javascript is not such a language, this is what we have to do....I'm not actually sure this whole thing was a joke, but it reads to me a little like it might've been written with the sort of smirk you tend to see academic FP purists directing at industry engineers.