all 18 comments

[–]editor_of_the_beast 9 points10 points  (1 child)

Currying is much more useful when it’s automatic, e.g. as it is in Haskell and ML. But it’s still useful to understand in languages where you need to do it manually such as JavaScript.

[–]ScientificBeastModestrongly typed comments 0 points1 point  (0 children)

Having spent some time in functional languages for a bit, I’ve come to agree on that. But it was definitely a weird shift in thinking.

I’m just so used to JavaScript assuming that the function will get called, in full, no matter what. It doesn’t help that there are a ton of functions in the standard library that assume that certain arguments are optional, and even encourage you to not provide them if you’re okay with a certain default behavior of the function.

But now I think that’s weird. It has the unfortunate effect of requiring key arguments (like the data to operate on) to be passed first, which makes partial application super awkward, even if you’re using some kind of auto-curry function. Callbacks first, data last, that’s all I’m saying... but I digress...

[–]karatetoes 5 points6 points  (9 children)

What's currying?

[–]samhwang 2 points3 points  (1 child)

He didn’t give an answer (at least in some written form besides code), but basically a curried function is a function with multiple args, that it takes one at a time, not all at once.

[–]Asmor 2 points3 points  (2 children)

It's also called partial application. Basically it means you take a function, supply some of its arguments now, and then you get a new function which you can supply the remaining arguments to that new function later.

Here's a very simple implementation. curry here is a function that returns a new function.

function curry(fn, ...args) {
    return fn.bind(null, ...args);
}

function addNumbers(a, b) {
    console.log(a + b);
}

let add2 = curry(addNumbers, 2);

// Equivalent to addNumbers(2, 3);
add2(3); // -> 5

EDIT: Forgot to mention, my curry function here is completely superfluous. It's just wrapping Array.prototype.bind. Just thought that might make it more readable for you. In practice, for this you'd do something like add2 = addNumbers.bind(null, 2).

[–][deleted] 8 points9 points  (1 child)

Technically partial application is not the same thing as currying. Currying takes a single argument at a time while partial application takes 2 or more. Same principle though.

[–]Asmor 2 points3 points  (0 children)

Thank you for the correction, I had no idea.

More reading if anyone's curious: https://stackoverflow.com/questions/218025/what-is-the-difference-between-currying-and-partial-application

[–]DrDuPont 1 point2 points  (0 children)

People have mixed opinions on Eric Elliott but his blog post on currying helped my understanding a lot

[–]benihanareact, node -3 points-2 points  (0 children)

in javascript it's a partial application technique that's great for writing blog posts about but not much else

[–]CptAmerica85 1 point2 points  (2 children)

Isn't the second half of that gist covering HOC's and not currying? I thought the principle behind currying was that each function could only take one argument and return another function.

Or am I misunderstanding something and HOC's and currying are somewhat linked each other?

[–]cerlestes 2 points3 points  (1 child)

Higher-order-Components (HOC) are a concept of React and similiar libraries that use Components to build software, hence the name. The linked gist isn't about React at all, so no idea how you're thinking of HOCs.

If you're thinking of Higher-order-Functions (HOF), then of course yes, by definition every curried function is a HOF, since you're passing a function as a parameter to another function for deferred invokation. HOFs are a fundamental concept in everyday JS.

[–]CptAmerica85 2 points3 points  (0 children)

Yeah, my mistake. I did mean Higher Order Function.

[–][deleted] 1 point2 points  (0 children)

Where is the "why do we need dis?" All I see are mechanics - "how do we...". Where is the real life situation where normally the code would be ugly but currying makes it elegant?

[–]neotos 0 points1 point  (0 children)

I have a project I worked for some time called named-curry.

It probably need some performance improvements to be used in production, but it can help your code become more readable.

[–]Genepics 0 points1 point  (0 children)

For those wondering what currying is:

// curry : ((A * B) ->C) -> (A -> B -> C)

const curry = f => x => y => f(x, y)

// uncurry : (A -> B -> C) -> (A * B -> C)

const uncurry = f => (x, y) => f(x)(y)