Skip to content

Instantly share code, notes, and snippets.

@Alexei-B Alexei-B/LICENSE.txt forked from 140bytes/LICENSE.txt
Last active Feb 13, 2017

Embed
What would you like to do?
curry functions in <140 bytes.
a = ( // Name the function for callback later.
b, // The function to curry.
c, // The scope to call within. (Defaults to global scope.)
...d // Arguments. (Defaults to empty array.)
) =>
d.length < b.length // If we don't have enough arguments yet.
&& // Use && and || to select to eliminate brackets from arrow function.
((...e) => // Return a function.
a( // Return the result of callback of curry func.
b, // Function.
c, // Scope.
...d, // Arguments we had already.
...e // New arguments.
))
|| // Else
b.apply(c,d) // Return result of applying arguments and scope to function.
a=(b,c,...d)=>d.length<b.length&&((...e)=>a(b,c,...d,...e))||b.apply(c,d)
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2015 Alexei Barnes <http://alexeibarnes.com>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "curry",
"description": "Turns functions into chainable curried function objects.",
"keywords": [
"curry",
"chained",
"recursive",
"functional",
"140bytes"
]
}
<!DOCTYPE html>
<title>Foo</title>
<div>Expected value: <b>10</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
var a=(b,c,...d)=>d.length<b.length&&((...e)=>a(b,c,...d,...e))||b.apply(c,d)
var obj = function() {};
obj.prototype = {
example : function(a, b, c, d) {
return a + b + c + d;
}
};
var Obj = new obj();
document.getElementById("ret").innerHTML = a(Obj.example, Obj, 1)(2)(3, 4);
</script>
@Alexei-B

This comment has been minimized.

Copy link
Owner Author

commented Aug 11, 2015

I really like how this turned out as I found most online examples of a generic curry function in javascript to be ugly as all heck. Note that this does not slice the arguments, meaning V8 won't have any problems here.

If you want a version of this that is a bit more readable then I recommend the following code:

function curry(fn, scope, args) {
    args = args || [];

    if (args.length >= fn.length)
        return fn.apply(scope, args);

    return function() {
        return curry(fn, scope,
                 args.concat.apply(args, arguments)
                );
    };
}

This code works in the same way however I've renamed the variables and reformatted it.

Here are some examples of using the function:

function example(a, b, c) {
  return a + b + c;
}

// typical use
var partial = curry(example)(1, 2);
partial(3) // 6
partial(4) // 7

// chained use
var partial2 = curry(example)(1);
partial2(2)(3) // 6
partial2(2)(4) // 7

// with optional arguments supplied
curry(example, window, [1, 2, 3]) // 6

// math functions
var pow2 = curry(Math.pow, Math)(2);
pow2(10) // 1024

// webgl functions
var canvas = document.createElement("canvas");
var gl = canvas.getContext("experimental-webgl");

var bindArrayBuffer = curry(gl.bindBuffer, gl)(gl.ARRAYBUFFER);

You can see a live version of the test code here: http://jsbin.com/rasema/edit?html,output

@Alexei-B

This comment has been minimized.

Copy link
Owner Author

commented Aug 11, 2015

Thanks to @jed for the examples, I just dropped this to 126 bytes after realising I could name the function as seen here: https://gist.github.com/jed/964769

@Alexei-B

This comment has been minimized.

Copy link
Owner Author

commented Aug 11, 2015

Just found out I can save 8 bytes removing the ||window after s because if you pass undefined to apply it will use the global scope.

@atk

This comment has been minimized.

Copy link

commented Aug 12, 2015

Save another character with the help of your friendly neighborhood JS code golf caddy:

function c(f,s,a){return(a=a||[]).length<f.length?function(){return c(f,s,a.concat.apply(a,arguments))}:f.apply(s,a)}
@Alexei-B

This comment has been minimized.

Copy link
Owner Author

commented Aug 12, 2015

@atk nice! I've updated it to match and also renamed the variables to follow the abc's I see a lot on 140bytes.

@atk

This comment has been minimized.

Copy link

commented Aug 12, 2015

The abc's is not a neccessarity; it's just easier to remember their order.

@Alexei-B

This comment has been minimized.

Copy link
Owner Author

commented Aug 12, 2015

Eh, if nothing else consistency is worth effort right?

@atk

This comment has been minimized.

Copy link

commented Aug 13, 2015

That's true 👍

@Alexei-B

This comment has been minimized.

Copy link
Owner Author

commented Jan 10, 2016

Thanks to ECMA6 this is now only 73 bytes, and makes more sense to call.

You can now follow the pattern shown here;

var temp = curry(fn, scope, arg1, arg2)(arg3);
temp(arg4, arg5)(arg6);

Additionally if you don't need a scope argument it can be reduced to 64 bytes:

a=(b,...c)=>c.length<b.length&&((...d)=>a(b,...c,...d))||b(...c)

Golf'd.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.