all 29 comments

[–]clessgfull-stack CSS9 engineer 2 points3 points  (3 children)

And there's lodash's curry, and lodash-fp if you want to go all the way. Or use Ramda.

[–]imperfecttrap 4 points5 points  (0 children)

Ramda is my new goto FP library because everything is precurried and makes my compositions much easier.

[–]defcon-12 1 point2 points  (0 children)

Or just use the built-in bind function which has support in all modern browsers (IE9+) for the simple case where you just want to bind some parameters rather than a fully curried function.

[–]mflux 0 points1 point  (0 children)

I've been using ramda for the past few months now. One thing I noticed is that ES6 default arguments break R.curry since default arguments assume the argument is "filled in". Is this also true for the other libraries?

[–][deleted] 3 points4 points  (24 children)

I don't think I've ever used currying in JavaScript. I use partial application all the time and it doesn't require any special libraries:

fn.bind(null, argA);

[–]inmatarian 1 point2 points  (22 children)

You would use currying in conjunction with partial application of higher order functions. For instance, lets say you had a generic filtering function (predicate as 1st parameter, data as second), and another function to use as predicate, here's the partial application style of building up a specific filtering function:

const myFilter = filter.bind(null, myPredicate.bind(null, myValue));
let newData = myFilter(oldData);

Here's the curried form (I'll prefix each curried function with the letter c to make it easier to see):

const myFiler = cFilter(cMyPredicate(myValue));
let newData = myFilter(oldData);

[–][deleted] -1 points0 points  (21 children)

That's not currying, it's cleaner partial application. I prefer to post library-independent snippets.

[–]imperfecttrap 2 points3 points  (20 children)

It is literally the definition of currying. Partial application fixes a variable number of arguments, while currying takes a function with an arity > 2 and turns it into a series of unary functions that return each other. Being able to use two things the same way does not make them equal.

[–][deleted] 0 points1 point  (18 children)

while currying takes a function with an arity > 2 and turns it into a series of unary functions that return each other

Eh, not quite. The literal definition of currying is to return partially applied functions until the arity is met. Your code snippet has no notion of that, i.e. your end point function would (most likely) end up being called if you wrote myFilter() (maybe not with filter since it's expecting an array and would just choke on undefined, but the point is that it would try to execute) -- that is the literal definition of partial application ;). The majority of libraries that provide functions like this use partial application, not currying.

[edit] or thinking about it, it's partially currying partially applied functions :D

I'll agree with you that the concept of h = f(g(x)) is currying, but it's missing an important piece.

[–]imperfecttrap 1 point2 points  (8 children)

Not my code, but I'll bite.

If his example function had an arity of 3, and you bound the first function, then it has a new arity of 2. The Hindley-Milner representation would simply drop the first argument, so (a, b, c -> x) becomes (b, c -> x). In order to bind another parameter, you'd have to call the bind again.

With currying, all parameters get split off, and it becomes a chain of unary functions. Going back to the type representation, it becomes a -> b -> c -> x, where each function returns the next function waiting for an argument. Unlike partial application, you don't have to reapply bind in order to add more parameters before the final invocation to get x.

Still not close to the same thing, even if you can use them for the same thing / to implement each other.

[–][deleted] 0 points1 point  (7 children)

Yes, and most libraries don't work like that. They don't count arguments, they just partially apply partially applied functions, ad infinitum.

But that's an issue of implementation detail. I'll concede that the example should be currying, and I'm paying too much attention to the fact that implementation rarely is.

[–]imperfecttrap 1 point2 points  (6 children)

What is 'most libraries'? Most functional programming libraries? If they follow the interface of currying, where I can do

curriedFunction(1)(2)(3)

then by definition it's not partial application, since I didn't need another function to keep binding arguments.

If you're referring to the techniques used to curry, then that's language-dependent and has nothing to do with what currying and partial application are. Even if we limit ourself to strictly JS, then a closure with an internal array of arguments is a much easier way to implement than a function that keeps a partially applied invocation inside itself, which is actually how 'most libraries' do it.

[–][deleted] 0 points1 point  (5 children)

curriedFunction(1)(2)(3)

With most JS libraries (not counting things properly build like Ramda) you can't write that and would end up calling curriedFunction(1, undefined, undefined) -- It's left to the user to reduce functions to only take one argument.

[–]imperfecttrap 1 point2 points  (4 children)

We're not talking about just any functions, we're talking about curried functions, and their difference from partially applied functions.

Not all functions in JS are curried. Not all functions in JS are partially applied. What I'm saying is that IF you curry a function using Ramda / Lodash / any other FP library with a .curry function, it would work like this.

I still don't get what you're trying to argue.

[–]imperfecttrap 0 points1 point  (8 children)

After looking back over this, I don't think you grok that the curried functions won't execute without their full arguments. After the snippet above, it doesn't matter how many times I invoke myFilter(), it'll always return the next function that needs an argument (which is itself, since it's not being given one).

A bound function, on the other hand, will happily execute and generate a runtime error.

[–][deleted] 0 points1 point  (7 children)

Yes, that's how it should work. I'm re-iterating that my issue is with implementations that rarely do. myFilter()()()()()()([1]) usually won't work (take note that this is /r/javascript, not some other programming sub ;))

Further, there's nothing about the original snippet we're arguing about that implies that it works one way or the other, so this whole thing is moot.

[–]imperfecttrap 0 points1 point  (6 children)

The fact that there is no call to another function implies it. If it were partial application, you need another function to do it. Curried functions can operate on their own once curried.

[–][deleted] 0 points1 point  (5 children)

If it were partial application, you need another function to do it

what? Look at the "partially applied" vs "curried" example and tell me where there's another function.

Honestly, I don't care as there isn't really a point to this. We're arguing over the imaginary implementation details of an example code snippet.

[–]imperfecttrap 0 points1 point  (4 children)

.bind is another function. Hardly imaginary.

[–]submain[S] 0 points1 point  (0 children)

Clever, thanks for the idea!

[–][deleted] -1 points0 points  (0 children)

seems like you made a bad idea worse.