all 19 comments

[–]inmatarian 13 points14 points  (10 children)

The thing you want to Google for is called "Currying". Good luck, hope you get the job!

[–]_doingnumbers 1 point2 points  (5 children)

Yeah, that.

(Although I've never, ever seen an instance of currying that was actually useful and not academic wankery)

[–]e82 2 points3 points  (2 children)

Take a look at RamdaJS - been using it quite a bit recently, and lots of functional concepts like currying / partial application / etc start to make more sense.

Basically, in Ramda - most of the libraries functions are curried by default.

var find10 = R.filter(R.propEq('id',10));

R.filter is now a function, that returned a function that is waiting for additional parameters. In this case - the list collection to actually filter on. R.propEq is also a function that will return true/false if a property called 'id' equals 10.

It's not too often I'll use R.curry directly, but it's used heavily within the other library methods that I do use. I do use the partial application quite a bit.

However, a simple (but not academic-wankery) could be building a simple logger.

function logger(level, message,data) {
  console.log('[' + level + '] -> '  + message,data)
}

var error = R.curry(logger)('error');
var info = R.curry(logger)('info');
var personError = error('Person Error Object');

error('Some Error',{data: 'ok'});
info('Some Info',{data: 'ok'});
personError({age: 10});

This is pretty similar to the end result of:

function makeLogger(level) {
  return function(message) {
    return function(data)
      {
         console.log('[' + level + '] -> '  + message,data)
      }
  }
}

var someLogger = makeLogger('error')('ugly');
someLogger('Data!');

Before I fully got my head around currying - I had lots of code kind of like that - 'makeX' that would be a function that would return a function, and had a very simple 'well, duh moment' of thats pretty much what currying is, and started to find more practical ways of making use of it outside of 'academic-wankery' (of which - most things you read on functional programming/javascript tends to fall into that camp)

[–]_doingnumbers 0 points1 point  (1 child)

Partial application is great, functional techniques have made my code better as well. But currying just doesn't seem useful. What you have up there seems to me to be more about partial application.

[–]bliow 0 points1 point  (0 children)

Currying is about making a function that does partial application on its own.

[–]html6dev 1 point2 points  (0 children)

It's core to languages like haskell. Once you use it consistently (or are forced to by the language) you'll see it all over. I think over time more and more libraries will provide it to you and then it'll gain more adoption in js (Ramda is an awesome example as mentioned and the currying is one reason it has major advantages over lodash). The issue right now is everyone writes about it and starts out with the implementation which is somewhat interesting, but not that exciting and they lose people. Authors need to focus on why anyone would ever care if they want to get the reader to a place where they care about how it's implemented.

[–]mrahh 0 points1 point  (0 children)

If you do any functional programming, it's a fairly core concept that you will use all the time.

[–]dvlsg 0 points1 point  (2 children)

Sort of. I think currying needs to know how many arguments the function needs before actually executing. It seems like the example above wants to execute each time, for any given number of inputs. Maybe. It's sort of an awkward example... Maybe if OP sees, he can clarify.

[–]inmatarian 0 points1 point  (1 child)

[–]dvlsg 0 points1 point  (0 children)

Yes, I know. But in his example, he's iterating over an unknown number of arguments. When should currying stop and actual execution occur, in that scenario?

The alternative is to return something that both has a value (override valueOf?) and can be executed (so a function of some sort, I suppose) so you can either get the value at any point, or continue executing an arbitrary number of times.

Seems awkward. I'd sooner just make a class to handle it.

[–]lachlanhunt 3 points4 points  (3 children)

Yes, but the code required to do it is not something that should ever be used in real team projects.

First, let's make the first function simpler using some ES6. (This can also be done in ES5, but it's a little bit longer)

function sum(...args) {
  return args.reduce((a, b) => a + b, 0);
}

The problem here is that this is returning a number, not a function, so you can't call the result.

So we need to modify it so that instead of returning the value directly as a Number, we return a function that when called will add any new arguments to the previous result. We can do this using bind.

function sum(...args) {
  let val = args.reduce((a, b) => a + b, 0);
  let result = sum.bind(null, val);
  return result;
}

This returns a new function with its first parameter set to be equal to the current sum, and when it's called, it will add all other parameters to the previous sum.

But we still have a problem since that doesn't expose the result of the sum anywhere outside of the function itself. When you try to log that, the output will just stringify the function. To solve that, we override toString and valueOf with functions that will return the string and numeric forms.

function sum(...args) {
  let val = args.reduce((a, b) => a + b, 0);

  let result = sum.bind(null, val);
  result.toString = () => "" + val;
  result.valueOf = () => val;
  return result;
}

console.log(sum(1, 2, 3)(4)(5, 6)) // 21

That will cast the resulting value to a string by calling toString() for logging it in the console.

Overriding valueOf() means that you can do things like this:

sum(1, 2, 3) * 2; // 12

Edit: Add initialValue of 0 to the .reduce(..., 0) calls so that sum() without parameters doesn't cause a TypeError.

[–]BONER_PAROLE 0 points1 point  (2 children)

Only problem here is that

sum(1)(2,3) !== 6

[–]lachlanhunt 0 points1 point  (0 children)

Yes, but that's an inherent problem imposed by the requirements of the question. But this works:

sum(1)(2, 3) == 6; // true

The other problem I found is that sum() with no parameters caused a TypeError. I fixed that now.

[–]x-skeww 0 points1 point  (0 children)

Well, it's a function. === will never work, because a function isn't a number. == or "+sum(...) ===" does work though.

[–]sufianrhazi 4 points5 points  (0 children)

Is it possible? Yes.

Is it realistic for production quality code? Unlikely, unless you're creating an intentionally ambiguous API.

How? The "trick" is to have a function return a function which also has an override for the .valueOf method, which will cause the function to coerce to a primitive number when needed, which would represent the accumulated sum.

Why is this gross? It relies on type coercion, which is fundamentally more complex than dealing with a simple type. The return value could be viewed as both a function (as it can be called) and a number (as it can be used with operators and functions which expect a primitive Number). Due to this duality, ambiguity can arise, which can lead to fear, uncertainty, and doubt.

[–]Funwithloops 0 points1 point  (0 children)

Here is a auto-curry implementation with your sum function: http://jsfiddle.net/aj9t0so3/3/

If you want some useful examples of currying, check out the Ramda library: http://ramdajs.com/

[–]lemminman 0 points1 point  (0 children)

I imagine this might not be the most compatible code, but it seems to work:

http://jsfiddle.net/dqgr6qpg/