Currying in JavaScript
medium.com
medium.com
Another problem with currying in Javascript is that it leads to more complicated stack traces, which is unfortunate for debugging.
The OP is already using Function.length (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...), so I suppose one could roll their own arity-checking. It'd be a little out of sync with the rest of the language, though.
If you have an uncurried function for which you have not supplied sufficient arguments, and it is eagerly evaluated, you more likely see below the call site an error in the function where an expected value is undefined. If the function is curried, the meat of the function remains unevaluated, and so is sure to give you back a value that isn't the one you want. So it does seem like moving to currying in JS is likely to sometimes increase error-to-symptom distance.
Does currying even make sense for variadic functions? I can't imagine what that would look like as an implementation.
This example here is a function that sums a variadic list of non-zero numbers. The zero signals the end of the list.
Its certainly very weird though. I wouldn't recommend doing this in real programs.
function reduce(nil, cons) {
return (ary) => {
...
}
}MDN documentation contains some very illustrative examples of its use:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Can't really do that with .bind without executing it.
That being said - well written, very informative, and I very much appreciated the simple and concise definition of currying.
Thanks.
It's been a while since the first time I ever tried to do this, so it's a bit difficult to remember exactly what my initial approach was. But I definitely remember the moment where I realized I needed the `resolver` function. Initially, I think I tried to just make `curry` return something that looked like the anonymous function inside of `resolver` – which of course didn't work, because I had no way to store all of the previous arguments.
Ultimately, I think there are probably a number of good ways to do this, and I would never claim that mine is the "right" one. It's really just a representation of the way I think about things, I guess.
If you do a bit of digging, there are some other great blog posts about currying, and each one has a different approach. It's actually pretty interesting to see how different people have implemented it. For a what basically amounts to a 10-line function, there's a pretty amazing amount of diversity in the way people approach it.
function curry(fn) {
return function accum(...args) {
if(args.length >= fn.length) {
return fn.apply(null, args)
}
return accum.bind(null, ...args)
}
}[1]:
http://www.mathscribe.com/author/jqmath.html
http://www.mathscribe.com/mathscribe/jqmath-0.4.3.js
[2]:
http://www.mathscribe.com/mathscribe/jscurry-0.4.0.js
http://www.mathscribe.com/mathscribe/jscurry-documentation.t...
Like if you had to call a method like this:
sendMessage(sender, receiver, data);
a bunch of times with the same receiver but different senders, you could define:
function sendMessageToBob(sender, data) { sendMessage(sender, bob, data); }
While that works for many cases it isn't generally true. For instance:
function wtf() { return arguments[0]; }
While that may seem like a ridiculous example, the following idiom is quite common in JS programming: function accessor(value) {
if (typeof value === 'undefined') {
return getValue();
}
else {
setValue(value):
}
}
In general it's not a good idea to expect any particular value for a function's length property.There are infinite examples for this sort of thing in real development scenarioes
So we can debate how often you’d need to curry a function, but I feel safe suggesting that writing your own curry function (or reading along with an essay that does the same with lively interest) is valuable.
Same with things like classes and mixins, there is now syntactic sugar for such things, but it’s always a good thing to have written your own MakeClass function at least once.
That was kind of my intent (learning exercise rather than super practical real-world technique) -- but I'll admit I probably could have picked a better title.
https://web.archive.org/web/20140714014530/http://hughfdjack...
Ramdajs: http://ramdajs.com/0.16/index.html
objects.map(get('id'))
and poof there goes your type safety. Optional typing (flow and TS) is making inroads into JS. If you want to bet on them (or any other JS inspecting tools), make sure you use this: objects.map(function (x) { return x.id; });
Or, in ES6 or TypeScript: objects.map(x => x.id)
This helps computers understand your code.However, it's the kind of bet I wouldn't go long on. Today, TS automatically (and correctly) infers the type of objs.map(x => x.foo). I suppose the same holds true for flow. This is not hypothetical; try this in http://www.typescriptlang.org/Playground
var objects = [
{
id: 1,
name: "Foo"
},
{
id: 2,
name: "Bar"
}
];
var look_at_my_type = objects.map(x => x.id);
Note; this is 100% JS, just passed through a TS compiler.Check the type of look_at_my_type (e.g. start typing its name at the bottom, see what the popover says): number[].
Replace it by get('id') (with definition function get(name: string) { return x => x[name]; }), and the type becomes any[].
Also (possibly related), what does 'arguments' in "Array.prototype.slice.call( arguments )" resolve to, and when? I would have thought it would be evaluated when 'resolver' in invoked, and would therefore evaluate to an empty array. If so, isn't there a simpler way to make an empty array?
The immediately invoked function is really just a slightly less verbose way to do this:
function resolver() {
}
return resolver();
The reason that I gave it a name instead of using an anonymous function (as is common with immediately invoked function expressions) is because I need to be able to call it from within itself. This function is all about creating a closure where we can store all of the arguments we've received so far.As for your second point: The first time that `resolver` is called, arguments is in fact empty. But if you read a bit further, you'll see that `resolver` calls itself recursively (indirectly, via the anonymous function it returns), and does in fact pass arguments. So you can't just start off with an empty array each time. You need to make sure you're taking into account any arguments that were passed in. Does that make sense?
That doesn't let you curry functions, but it does give you partial application, which I think is actually more useful on a day-to-day basis. If you're not familiar, here's a very quick and admittedly somewhat contrived example:
function clamp( lo, hi, val ) {
return Math.max( lo, Math.min( hi, val ) );
}
var tenToTwenty = clamp.bind( null, 10, 20 );
tenToTwenty( 5 ); // 10
tenToTwenty( 15 ); // 15
tenToTwenty( 25 ); // 20
For what it's worth though, I agree that having Function#curry in the ES spec would be pretty cool.If performance matters native bind() can be a pain.
If I'm writing some super perf-sensitive code like manipulating an array of PCM data for Web Audio stuff or doing a complex canvas animation, then the savings of not using Function#bind are probably kind of important.
For most everyday code, avoiding bind() kind of feels like premature optimization to me.
I spent a few hours removing it from a codebase of mine last week, to see substantial improvements on all browsers.
That said I don't see the applications for currying in JavaScript. It just makes code less readable. It looks like an anti-pattern to me.
https://web.archive.org/web/20141121220218/http://jsperf.com...
http://v8.googlecode.com/svn/trunk/src/v8natives.js
Another interesting example is Babel. In a fat arrow function, they would rather replace every instance of 'this' with a generated variable than add a .bind() to the end strictly based on overall performance.
The second problem is surprising for everyone. The only thing you will see is that just before you enter the function, the 'this' is correct and immediately after, the 'this' changes. I've only ever spoke with a handful of devs who know this behavior happens.
The biggest issue here is that if I use a third-party library and an external interface ever calls .bind(), then the abstraction will absolutely fall apart in a variety of circumstances.
Considering that a simple `var self = this;` works in 99% of cases, I see no reason to encourage programmers to use .bind() in their code.
Please tell me why you throwing reams of source code in my face is relevant.
> In a fat arrow function, they would rather replace every instance of 'this' with a generated variable than add a .bind() to the end strictly based on overall performance.
Source? Or could it be, shock, that a library that exists for compatibility is targeting environments without a native .bind()?
> The second problem is surprising for everyone.
It's only surprising for people who have never tried, never read the spec, and don't understand bind(). The spec clearly states that a bound function cannot be overridden. It's really not that difficult. It would be nice if you could provide clear examples of your problems because you're starting to not make sense.
Because the bind function implementation shows why it is so slow. If you read the spec like you imply, then reading one function shouldn't be difficult. You can write your own 'bind' function that skips a bunch of uncommon corner cases and get a huge boost in performance. Deal with the possible edge cases and performance tanks.
> Source? Or could it be, shock, that a library that exists for compatibility is targeting environments without a native .bind()?
It's not a matter of supporting older browsers. Babel target's IE9+ by default and has optional polyfills and transformers you must add if you want to support JS versions before ES5.1.
There was a discussion on Reddit about this very topic a few months ago. The poster got served by the Babel guys and deleted all their posts. Their claim was basically that `(foo) => this.foo` should translate into `function (foo) { return this.foo; }.bind(this)` and that Babel got it wrong. The response from sebmck was "There's no point in using bind when you can just remap all references to this which is significantly faster." [source](https://www.reddit.com/r/webdev/comments/30wwgk/an_overview_...).
If you want to know more on the topic, I'd suggest making a github issue so one of their team members can clarify things for you.
> It's only surprising for people who have never tried, never read the spec, and don't understand bind(). The spec clearly states that a bound function cannot be overridden. It's really not that difficult. It would be nice if you could provide clear examples of your problems because you're starting to not make sense.
The spec is fairly obscure about thisArg vs [[BoundThis]] and a full understanding encompasses not only a half-dozen user and internal functions, but also requires the reading about environments. This gets even more opaque in the ES2015 spec. That said, 99.5% of JS programmers will never read the spec (the ES5.1 spec is ~300 pages of extremely technical reading while the ES6 spec is ~600 pages and even harder to understand).
Here's a made-up example
var obj1 = {foo: 3};
var obj2 = {foo: 4};
var add = function (n) { return n + this.foo; }.bind(obj1);
add.call(obj2, 3); //=> 6
This may be easier to see in this little example, but if that definition is somewhere in a library and you use a .call() with a `this` that matters, your function will fail. When you step through with the debugger, you will see that your object that you're passing as the `this` is what you expect. When you step into the function, it will have suddenly changed to a different object.I assume the silent failure is because users may want to .apply() a function that is bound for the easy array destructuring, but I think that attempting to rebind the `this` too anything but null or undefined should yield an error of some kind.
Does it? I'm not going to pretend to know why that would be. Your explanation would be welcome.
I don't know if this sebmck fellow has benchmarked the code, but another commenter below found it to be a whopping 25% faster. Micro-optimizations, anyone?
> 99.5% of JS programmers will never read the spec
You don't have to read the spec, it's literally the first thing after the description paragraph on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
As others have mentioned, when I bind a function, I don't expect it to be able to be messed with.
Anyway, I'm done debating, but it should be quite obvious that there's no need to throw bind() away.
In FF39 on my machine, .bind() is between 5 and 20x slower. In Chrome 43, it's between 2 and 20x slower compared to call and apply and 200x slower compared to normal function calls (I ran several times and don't fully understand why Chrome optimizes the hell out of normal function calls).
I would encourage you to run it for yourself and see.
Personally, I'd say the described behaviour made sense. If I bound a function, I'd want its `this` to remain bound, regardless of how I called it. That'w what one uses `.bind()` for. It seems counter-intuitive, to me, that one might want to explicitly `.bind()` something and then use it as if it had never been bound. In that case I'd `.call()` the original function with the new content object, rather than `.call()` the bound one.
var cl = function () { console.log.apply(console, arguments); };