4 ms·
Forgive my ignorance, I'd would like an example of the "functional" (hehe) benefits of automatic currying
by kupopuffs 4y ago
Forgive my ignorance, I'd would like an example of the "functional" (hehe) benefits of automatic currying
- earth_walker 4y agoPartial application and function composition are the meat-and-potatoes of functional programming. Automatic currying is syntactic sugar that can make these two easier and clearer as it gets rid of a bunch of named arguments and lambdas. For example, I can write: foo a b c = a * b + c I can then apply this partially like this (foo2 just takes argument c): foo2 = foo 10 20 and compose it with other functions, for example like this: composed = foo2 >> bar >> baz Without currying, you'd have something like: foo (a, b, c) = a * b + c foo2 (z) = foo (10, 20, z) composed (a) = (\b -> foo2 (b)) ((\c -> bar (c)) (baz (a)))
- deleted 4y ago[deleted]
- agent281 4y agoBefore I start, let me say that I'm on mobile and I don't know how to post code on this site. I'm assuming backticks work. --- One benefit is that functions are more reusable. Functions with more arguments can be partially applied and used where applicable. For instance, if you wanted to increment the values in a list you might do something like this in python: map(lambda x: x + 1, [1,2,3]) But in an ML like language you can do something like: map((+ 1), [1,2,3]) Because plus is actually a function that takes two arguments and can be curried down to one argument. Additionally, you can think of currying as a form of dependency injection. For example, if you wanted to inject a database client and a logger before running a query you might do something like this: def queryer(db, logger): def _q(query): logger.info("before query") results = db.fetch(query) logger.info("after query") return results return _q rows = queryer(db, logger)(query) You could write it a bit more simply in this hypothetical ML like language: queryer db logger query = logger.info("before query") results = db.fetch(query) logger.info("after query") results MLs don't require parens/commas for function calls, but you can use parens to force a particular execution order. The lines below have the same result, but some produce and execute intermediate curried functions rows = queryer db logger query rows = (queryer db) logger query rows = ((queryer db) logger) query It's a bit contrived, but you have the flexibility to provide some arguments based on the call site rather than the definition site. I.e., the first example was broken up into 2 function calls at the definition site, but the second example could have 1, 2, or 3 function calls. --- I hope this makes sense and I wish I could preview my comment to see if it was formatted reasonably!
- anon_d 4y agoI find this phrase "Automatic Currying" that people are using in this thread to be very strange. It implies that `(add 3)` is being magically converted into `(\x -> (add 3 x))` by some fancy front-end feature. But no, `add` is just a function that returns a function. This pattern is core to the entire paradigm of functional programming, all the way down to the lambda calculus. All functional programming languages are essentially just fancy syntax around lambda calculus. They have different implementation strategies (strict vs lazy), different type systems, and they have been extended with different primitives (floats, operations on floats, etc). But at their core, they are all just lambda calculus. In the lambda calculus, there is ONLY functions, and all functions take one argument. There are no tuples. So, multiple arguments are implemented with the pattern in question. For example: mul = (λx. λy. λz. x(yz))