5 ms·
When you pass some arguments to a constructor and then later, you pass some more arguments to a method, that’s equivalent to currying. Method calls are easier
by skybrian 3y ago
When you pass some arguments to a constructor and then later, you pass some more arguments to a method, that’s equivalent to currying.
Method calls are easier to read and work better with autocomplete.
- whilenot-dev 3y agoI think you confuse currying with partial application.
- kerkeslager 3y agoAre you saying this to be helpful, or just to show you're smarter? If you're saying this to be helpful, you should probably explain more. Currying is a subset of partial application, so I suspect the person you're responding to is just being a bit loose with their wording, as opposed to not understanding the topic.
- whilenot-dev 3y agoI don't read it that way, no. Currying is a process to transform a function that takes multiple arguments into higher order functions that take one argument at a time to enable partial application (as written in the article). The partial application of a function is a different transformation of a function. Some languages provide partial application without currying a function - JavaScript has bind, Python has functools.partial etc.
- kerkeslager 3y agoOkay, I understand what you're saying, and you're right, but you're missing my point and doubling down on the same mistake again. Language is inherently imprecise and communication is never perfect. When people say something, it's rude to assume they are wrong or don't understand something because they don't say it exactly the way you would have said it. This is extremely common in technical communication and it's extremely counterproductive. I'm suggesting that you could be a better reader by trying to understand what people are trying to say even if they don't communicate it exactly the way you want them to. For example, no one in this comment chain is confused about what currying or partial application are, so it's a bit rude that you've assumed people are confused because you didn't take the time to figure out what people were trying to communicate. Instead, because people didn't say things exactly the way you would have said it, you jumped in with corrections. If you take a step back and resist the urge to correct people, can you understand how "Currying is a subset of partial application" is true?
- whilenot-dev 3y ago> ...can you understand how "Currying is a subset of partial application" is true? It isn't true and i can understand why someone would make that statement. Currying and partial application both come from a functional mindset that treats functions as data, and like data also functions can be transformed. Currying and partial application both satisfy a transformation depending on a desired context: - Currying "widens" a function "up" (as in you don't need to know all arguments beforehand in the same context anymore) - Partial application "narrows" a function "down" (as in arguments are contained within the context of the partially applied function) "Currying is a subset of partial application" is true in the same sense as if "subtraction is a subset of addition". Sure, you can subtract negative values to have addition and add negative values to have subtraction, but that can't be your point, is it? > If you take a step back and resist the urge to correct people... Please keep it on topic.
- kerkeslager 3y ago> It isn't true and i can understand why someone would make that statement It is true, and you are smart enough to understand it if you stop assuming you're the only one who understands the topic. I'm specifically sticking with the wording "Currying is a subset of partial application" to make the point that you can understand what someone is trying to say even if they don't say it exactly the way you would like them to say it. > - Currying "widens" a function "up" (as in you don't need to know all arguments beforehand in the same context anymore) > - Partial application "narrows" a function "down" (as in arguments are contained within the context of the partially applied function) So you're saying that I'm "widening" the function "up" when I do: increment = add 1 invert = div 1 ...? But I'm "narrowing" the function "down" when I do: increment = (\x -> add 1 x) halve = (\x -> div x 2) ...? When I curry `add` above, isn't the argument 1 contained within the context of the partially applied function? When I partially apply `div` above, don't I no longer have to know all the arguments (i.e. I no longer need to know the denominator 2)? It sure seems like this up/down wide/narrow wording you're fixated on isn't a particularly better descriptions of what's going on with currying and partial application. It mean, maybe it's just my font, but the partial applications are a bit wider on my screen. ;P > "Currying is a subset of partial application" is true in the same sense as if "subtraction is a subset of addition". Sure, you can subtract negative values to have addition and add negative values to have subtraction, but that can't be your point, is it? I'm not sure I understand that analogy to say it's my point. Are you saying you would behave condescendingly toward someone who said "subtraction is a subset of addition" too? > Please keep it on topic. The topic skybrian started was derailed when you decided to "correct" him because you didn't make any effort to understand what he was trying to say. Your behavior is the topic now because your behavior became a problem.
- threatofrain 3y agoI thought it was somewhat the reverse — that the original motivation was to simulate multi-arity functions in a setting that only allows unary functions.
- bPspGiJT8Y 3y agoI don't really understand the distinction between "multi-arity" and "unary" functions. In my mental model, all functions are unary, it's just that in "traditional", non-FP languages it's more common to pack arguments into tuples. That is `(a, b, c) => ...` in JS is a unary function which takes a tuple of 3 items. But the thing is, FP has tuples too (and in Haskell, with pretty much the same syntax), it's just that most of the time arguments aren't packed into tuples. So could you elaborate to me where the distinction lies here and why is there a need to "simulate" things?
- jraph 3y agoSay you are dealing with a callback mechanism that takes a function and (only) one value to pass: function c(f, v) { ... f(v) ... } But what you actually need this callback mechanism to call is a function that takes two arguments. No default values. function f2(a, b) { ... } There's no way in js that c is going to call f2 and set its b parameter to something. You can't set v to be a tuple so b will be filled: c(f2, "value") => b will be undefined. c(f2, [1, 2]) => a will be set to [1, 2]. you need to wrap f2 for this when calling c: function wrapf2(b) { return f2("fixed a", b) } Or you can make c deconstruct v, or use apply: function c(f, v) { ... f(...v) ... } function c(f, v) { ... f.apply(null, v) ... } but then v always needs to be an array: c(f, [1]) c(f, [1, 2]) c(f, 1) // fails This is why in Javascript, multi-arity is different from unary with tuples. JS doesn't have tuples as a primitive / first-class type anyway. In some math notations we don't make the difference, but in most programming languages there's a distinction. Your model where functions are always unary but can take tuples, and (v) is the same as v, is correct (and useful when the distinction doesn't matter and is just annoying to deal with), but doesn't match the way many programming languages actually work. I believe even in most functional programming languages, (v) is different from v, you also said it. In assembly, different parameters are in fully separate registers or stack entries. Interestingly, you could imagine representing tuples as C structs (that can have only one member) and always pass structs, and passing a one-member struct will actually have the exact same effect as passing a value of a primitive type.
- Hirrolot 3y agoCurrying and partial application are dualities (think of them as function introduction/function elimination), so neither subsumes the other one. However, I agree with the wording of the original comment: when you _pass_ some arguments to a constructor and then to a method, this is (at least conceptually) partial application.
- kerkeslager 3y ago> Currying and partial application are dualities (think of them as function introduction/function elimination), so neither subsumes the other one. Could you say more? I'm not sure I understand what you're saying here.
- skybrian 3y agoYou can think of them as equivalent ways to write the same code. There are mechanical rewrites to go from one to the other, and these rewrites work in any direction. Which way is more readable depends on circumstances. When a function needs a lot of parameters to do a calculation, these parameters can be arbitrarily grouped into records and supplied in any order. Languages have convenient syntaxes for certain ways of grouping parameters together. For example, a closure creates a group of parameters in the form of a function.
- xeonmc 3y agoCurrying wraps, partial application unwraps.
- kazinator 3y ago> Currying is a subset of partial application No, it isn't; it's a different operation. Currying refers to building (effectively) functions of multiple arguments out of only one argument functions (such as in a language that has only those). A curried function is not understood to have been applied, partially or otherwise; none of its arguments have been bound to values, thereby reducing its arity. Partial application is an operation that requires one or more arguments. Currying does not require arguments; rather, the result of currying requires arguments (all of them). There is a sort of partial application (effectively) going on when the curried function is applied to the arguments, which has to be done one argument at a time through the chain. At each step, one more argument is bound, and fewer remain.
- ReleaseCandidat 3y agoNo, not exactly. And partial application of any function is nowadays possible using anonymous functions to wrap the original one, no need for constructors and special methods. What currying in Haskell and any other ML does, is the following as Javascript. Let's say we have a function with four parameters `func(a, b, c, d) {return a + b + c + d;}`, then the curried version is the following: func = (a) => { return (b) => { return (c) => { return (d) => a + b + c + d; } } }
- kerkeslager 3y agoYou're assuming that the poster doesn't understand what currying is and you're jumping in with a correction which is kinda rude. Instead of assuming you know better and jumping in with a correction, could you reread that post and assume that the person knows what they're talking about but isn't communicating exactly the way you would have communicated it? I.e., read with the intent of understanding intent, rather than read with the intent of correcting?
- ReleaseCandidat 3y ago> but isn't communicating exactly the way you would have communicated it? My answers are almost always less intented for the person who's post I'm responding to, but more for a general audience. As others have already posted the part about "currying isn't partial application", and I mainly wanted to add a (hopefully) understanable example. And I would say that taking the OP's post as if he doesn't exactly know, what currying means in comparison to partia application _is_ the more favourable interpretation of their post.
- kerkeslager 3y ago> My answers are almost always less intented for the person who's post I'm responding to, but more for a general audience Same. I don't expect you're going to admit your mistake, but I'm pointing it out because the general audience is the sort of audience who is prone to this mistake (which I only know because I myself have been corrected for making this mistake). > As others have already posted the part about "currying isn't partial application", and I mainly wanted to add a (hopefully) understanable example. And in doing so, you're making the same mistake as those other posters, by assuming skybrian doesn't know what currying and partial application are. You're not doing your audience any favors by painting skybrian's post as if he said something wrong. > And I would say that taking the OP's post as if he doesn't exactly know, what currying means in comparison to partia application _is_ the more favourable interpretation of their post. How so?
- Hirrolot 3y agoThe technique you describe requires us to predict what data should be partially applied (before actually using it), and what data should be applied and used immediately. In contrast, currying/partial application doesn't require this decision from us -- for this reason I consider the functional approach more flexible than the object-oriented one. In addition to that, I don't always find the constructor/method approach more readable. It _can_ be readable, if you design your API with care; however, it is common to group related data into records in the FP world as well, which mimicks OOP constructors, in a sense.
- skybrian 3y agoYes, like many refactorings, rewriting a function as an immutable class with a method is not always a win. It depends on how you want to group a function’s parameters, whether that grouping has an intuitive name, and whether you might want to write other methods that take the same initial parameters. Sometimes grouping parameters using a record type is better, though you don’t get the nice syntax. If currying isn’t built-in, you can emulate it. In TypeScript you need to do it explicitly, which means anticipating that it will be used, and whenever I try that, I later decide that it’s needlessly obscure and rewrite the code some other way. Even with built-in currying, you still need to anticipate usage by changing the order of the parameters, based on which ones you expect the callers to have first. It’s less general than writing an inline function with exactly the parameters you need. TypeScript has nice syntax for defining tiny, one-off functions and I think that’s better than having currying. One side-effect of having currying in a language is that it discourages naming things, and I think that’s often bad for readability. A chain of method calls gives you a lot of names to look up and a place to put documentation.