3 ms·
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'
by tommikaikkonen 9y ago
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've spent more hours than I'd like to admit debugging these situations.
A type system would detect these cases, but TypeScript and Flow don't have great support for curried functions. Typing them is very verbose.
- Tade0 9y agoI've been using currying (via http://ramdajs.com/ http://ramdajs.com/) in my projects for a while now and this is rarely a problem(yay for anecdotal evidence). One reason for that is that my curried functions and their derivatives are usually named in a way that says exactly what they do.
- ceronman 9y agoI 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.
- chrisweekly 9y agoI beg to differ. Auto-currying (eg via Ramda) is awesome, powerful, and pragmatic.
- skishore 9y agoThe 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.
- noshbrinken 9y agoI can't speak to Typescript but check out the Flow types for Ramda: https://github.com/flowtype/flow-typed/blob/master/definitions/npm/ramda_v0.x.x/flow_v0.39.x-/ramda_v0.x.x.js https://github.com/flowtype/flow-typed/blob/master/definitio... Maybe just a matter of perception but it looks verbose to me.
- tommikaikkonen 9y agoI agree, that doesn't look bad. However, this type definition forces you to supply one argument per function call, which looks awful in JavaScript: fn(1)(2)(3) That's a big drawback for me. Libraries like Ramda allow one or more arguments per function call: fn(1, 2, 3) === fn(1, 2)(3) === fn(1)(2, 3) That's what makes the verbosity unbearable, as each type of call needs its own type.
- noppa 9y agoAt least in Flow it's actually possible to properly type curried functions! Here's a gist of the type definitions I'm using: https://gist.github.com/noppa/c600cc43fd44e33768efe6c6eec4a99a https://gist.github.com/noppa/c600cc43fd44e33768efe6c6eec4a9... I think something similar might work in TS too. Demo: https://goo.gl/w3aPsw https://goo.gl/w3aPsw
- kuschku 9y agoWhile Java’s option is quite painful Function<Number, Function<Number, Function<Number, Number>>> The same in Kotlin is actually okayish: (Number) -> (Number) -> (Number) -> Number
- cle 9y agoNot only do you need to remember the arity, but the order as well, which is IMO worse (at least a type system can protect you from arity mistakes). If your function is not commutative for adjacent arguments of the same type, you're skipping through a minefield if you rely on currying.
- ajanuary 9y agoHow is that any different from having to remember the argument order in normal function application?
- cle 9y agoConceptually it's not that different. Practically, it's pretty different because you're effectively fragmenting a single function application across your codebase, making it harder to reason about and more likely to make ordering mistakes.