Skip to content

Instantly share code, notes, and snippets.

@Alexei-B
Forked from 140bytes/LICENSE.txt
Last active February 13, 2017 16:17
Show Gist options
  • Save Alexei-B/9a6abe497d4081917dac to your computer and use it in GitHub Desktop.
Save Alexei-B/9a6abe497d4081917dac to your computer and use it in GitHub Desktop.
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
Copy link
Author

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
Copy link
Author

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
Copy link
Author

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
Copy link

atk 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
Copy link
Author

@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
Copy link

atk commented Aug 12, 2015

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

@Alexei-B
Copy link
Author

Eh, if nothing else consistency is worth effort right?

@atk
Copy link

atk commented Aug 13, 2015

That's true 👍

@Alexei-B
Copy link
Author

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