Live data from Hacker News

Currying vs. Partial Application (2015)

datchley.name

21–30 of 54 posts

Re: Currying vs. Partial Application (2015)

#21

Currying in JavaScript is really nice if you can remember the arities of each curried function you're using. If you forget to call up to the last argument, you'll be passing a curried function instead of the expected value, and it can throw an error really far away from the bug. And instead of normal data to inspect at the error site to point you to the bad call, you'll only have a generic function name to look at. I…

I think this exact problem is what makes currying in JS and dynamically typed languages not very practical.

In JS is even worse because of the weak typing, if by mistake you get a curried function instead of a value, JS will happily operate on it giving you things like "hellofunction () {}". When you realize that there is a problem, it would be hard to find the actual cause of the error.

I think this is the reason why dynamic functional languages such as Clojure don't use auto-currying. I a static typed world, like Haskell's this is not a problem at all.

Partial application on the other hand is very useful and practical in JS and other dynamic languages.

Re: Currying vs. Partial Application (2015)

#22
This is interesting, but just because you can do something doesn't mean you should, particularly in JavaScript. As soon as I started working on a large project with a team of devs my coding style began to change dramatically. Simplicity and readability become paramount. Minimize how much a dev needs to understand about the code before they can work on it, and how long it takes them to read it. With the right coding conventions, anyone can start working within seconds just by seeing the names of the functions and variables.

The mental gymnastics required to read these functions and understand how they work is not negligible, it adds up. Especially when the function definition might be in another file from the one you are working on.

If any of my co-workers started actually using these techniques in our code, I would flag it. Usually, if you find yourself in a situation where it is beneficial to use techniques like this, it's a sign that you might be able to refactor your entire approach to make the design simpler.

Re: Currying vs. Partial Application (2015)

#23
post #6

Currying in JavaScript is really nice if you can remember the arities of each curried function you're using. If you forget to call up to the last argument, you'll be passing a curried function instead of the expected value, and it can throw an error really far away from the bug. And instead of normal data to inspect at the error site to point you to the bad call, you'll only have a generic function name to look at. I…

The type of a curried function in Typescript is just something like: (a: number) => (b: number) => (c: number) => number Sure, the parameter names and parentheses are a bit annoying, but I wouldn't call that "very verbose". Comparable concepts in C++ or Java would be a nightmare to type out.

While Java’s option is quite painful

    Function>>
The same in Kotlin is actually okayish:

    (Number) -> (Number) -> (Number) -> Number

Re: Currying vs. Partial Application (2015)

#24
post #22

This is interesting, but just because you can do something doesn't mean you should, particularly in JavaScript. As soon as I started working on a large project with a team of devs my coding style began to change dramatically. Simplicity and readability become paramount. Minimize how much a dev needs to understand about the code before they can work on it, and how long it takes them to read it. With the right coding c…

> The mental gymnastics required to read these functions and understand how they work is not negligible, it adds up.

While I agree with avoiding unnecessary complication, partial application is no more complicated than object construction, something you've presumably been doing all your life. Every time you create an object whose only initialization logic is to set some internal variables, you are effectively partially applying a function whose arguments are (0) the constructor's arguments, and (1) a method selector. No mental gymnastics are required to understand this. (And this doesn't take into account open recursion, which makes object construction more complicated in ways that mere partial application isn't.)

Re: Currying vs. Partial Application (2015)

#25
post #5

Earlier quoted context omitted.

appear incredibly simple*️

In what way is it not simple? It's hard to tell what you mean. The syntax is actually a bit of a nightmare if you are writing a parser, but from the perspective of a human reader, it shows you exactly what's going on under the hood.

I think, as others above, parent meant to say "simple to write but not to use".

Re: Currying vs. Partial Application (2015)

#27
{lambda talk} doesn't know closures but accepts de facto partial application:

1) just define function as usual:

  {def add 
   {lambda {:a :b :c} 
    {+ :a :b :c}
  }} - > add
2) and use it:

  {add 1 2 3}   -> 6
  {{add 1} 2 3} -> 6
  {{add 1 2} 3} -> 6
  {{{add 1} 2} 3} -> 6
More to see in http://lambdaway.free.fr/workshop/?view=curry

Re: Currying vs. Partial Application (2015)

#28
post #22

This is interesting, but just because you can do something doesn't mean you should, particularly in JavaScript. As soon as I started working on a large project with a team of devs my coding style began to change dramatically. Simplicity and readability become paramount. Minimize how much a dev needs to understand about the code before they can work on it, and how long it takes them to read it. With the right coding c…

> The mental gymnastics required to read these functions and understand how they work is not negligible, it adds up. While I agree with avoiding unnecessary complication, partial application is no more complicated than object construction, something you've presumably been doing all your life. Every time you create an object whose only initialization logic is to set some internal variables, you are effectively partial…

That's a fair point, currying is the main offender here, partial application is just making a new function. With the right name it's not harder to understand. It does add complexity because you have layers of dependencies instead of everything being in the same place. The example is always some simple math, but usually functions are doing more, and when they get changed it isn't always obvious that the things that rely on partial applications of those functions are also affected.

But that is true of anything that uses any dependencies, and a fundamental part of how we usually code. I prefer to reasonably minimize the number of dependencies, and then of course good tests protect you against this problem.

Re: Currying vs. Partial Application (2015)

#29

Currying in JavaScript is really nice if you can remember the arities of each curried function you're using. If you forget to call up to the last argument, you'll be passing a curried function instead of the expected value, and it can throw an error really far away from the bug. And instead of normal data to inspect at the error site to point you to the bad call, you'll only have a generic function name to look at. I…

I think this exact problem is what makes currying in JS and dynamically typed languages not very practical. In JS is even worse because of the weak typing, if by mistake you get a curried function instead of a value, JS will happily operate on it giving you things like "hellofunction () {}". When you realize that there is a problem, it would be hard to find the actual cause of the error. I think this is the reason wh…

I beg to differ. Auto-currying (eg via Ramda) is awesome, powerful, and pragmatic.

Re: Currying vs. Partial Application (2015)

#30

Ok, it might be too early in the morning, but I still don't understand this. I read that post, and the post by 'raganwald that the former linked to, and I still don't see any difference between currying and partial application. And yet both posts seem to imply (without showing in any way) that the two concepts are different. How come?

Partial application (passing too few arguments to a function) is something that a programmer does. Function currying is something that a programming language does in response to partial application. It's basically wrapping the partially applied function in another one that expects the missing arguments and then performs the originally intended computation.

Currying is something the programmer has to do when defining a function - well before partial application happens at all! More precisely, the programmer has to choose between:

    fun foo (x, y) = ...
And

    fun foo x y = ...
The language won't make the choice for them.
Post reply on HN