DEV Community

Cover image for Explaining currying to myself

Explaining currying to myself

Damien Cosset on September 18, 2017

Introduction Well, time to teach myself something I don't understand again... In this article, we will explore a technique called curryi...
Collapse
 
mikkpr profile image
Mikk Pristavka

Great article, Damien! There are just a few things I noticed in the definition of the curried function.
return fn( ...args ) should be return func( ...args ), I think.
Also, I don't quite get why you're defining nextFunc as an argument to the curried function. Is it just to declare the variable so that you wouldn't have to explicitly declare it inside the arrow function body and leave out the brackets? Just a bit unclear to me.

Collapse
 
damcosset profile image
Damien Cosset • Edited

Oh, you are right, it should be func and not fn. Thank you, I updated the code.

You know what, I actually have an issue with that. If I remove nextFunc from the arguments, I have an TypeError when I call my curried function.

But, when I implement my same curried function using the function keyword :

function curried(func,arity = func.length) {
  return (function nextCurried(prevArgs){
    return function curried(nextArg){
      let args = prevArgs.concat( [nextArg] );

      if (args.length >= arity) {
        return func( ...args );
      }
      else {
        return nextCurried( args );
      }
    };
  })( [] )
}

I don't need to specify this third argument. My guess is ( and it's only a guess so far ) that the arrow functions somehow changes something in my implementation. I'll dig a bit more. Good question!

Collapse
 
mikkpr profile image
Mikk Pristavka • Edited

And don't forget to also change the default value of arity from fn.length to func.length :)

Collapse
 
eljayadobe profile image
Eljay-Adobe

You can also do currying directly without having a curry-fier.

For example...

const cf = (a) => (b) => (c) => (d) => { return a + b * c - d; }

One of the things that I like about "functional-first" functional programming languages is that currying is the norm (as is immutability, concise syntax, pattern matching, non-nullable references, tail recursion, emphasis on purity), and you'd have to go out of your way to not do currying. For example, in F#:

let cf a b c d = a + b * c - d

That function is curried. And partial application is equally easy and straightforward:

let pa x y = cf 10 20

Collapse
 
damcosset profile image
Damien Cosset

It does take more discipline to use the functional side of Javascript. I think I added a curry-fier because I wanted to play around with the number of arguments. But it does make it less readable.

Collapse
 
bobbypriambodo profile image
Bobby Priambodo

The curried function with all its parens looks a bit too codegolf-ish :D I think there are opportunities to make it clearer.

But overall, great article!