I quite often see on the Internet various complaints that other peoples examples of currying are not currying, but are actually just partial application.
I've not found a decent explanation of what partial application is, or how it differs from currying. There seems to be a general confusion, with equivalent examples being described as currying in some places, and partial application in others.
Could someone provide me with a definition of both terms, and details of how they differ?
Currying is converting a single function of n arguments into n functions with a single argument each. Given the following function:
function f(x,y,z) { z(x(y));}
When curried, becomes:
function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }
In order to get the full application of f(x,y,z), you need to do this:
f(x)(y)(z);
Many functional languages let you write f x y z. If you only call f x y or f(x)(y) then you get a partially-applied function—the return value is a closure of lambda(z){z(x(y))} with passed-in the values of x and y to f(x,y).
One way to use partial application is to define functions as partial applications of generalized functions, like fold:
function fold(combineFunction, accumulator, list) {/* ... */}
function sum = curry(fold)(lambda(accum,e){e+accum}))(0);
function length = curry(fold)(lambda(accum,_){1+accum})(empty-list);
function reverse = curry(fold)(lambda(accum,e){concat(e,accum)})(empty-list);
/* ... */
#list = [1, 2, 3, 4]
sum(list) //returns 10
#f = fold(lambda(accum,e){e+accum}) //f = lambda(accumulator,list) {/*...*/}
f(0,list) //returns 10
#g = f(0) //same as sum
g(list) //returns 10
The easiest way to see how they differ is to consider a real example. Let's assume that we have a function Add which takes 2 numbers as input and returns a number as output, e.g. Add(7, 5) returns 12. In this case:
Partial applying the function Add with a value 7 will give us a new function as output. That function itself takes 1 number as input and outputs a number. As such:
Partial(Add, 7); // returns a function f2 as output
// f2 takes 1 number as input and returns a number as output
So we can do this:
f2 = Partial(Add, 7);
f2(5); // returns 12;
// f2(7)(5) is just a syntactic shortcut
Currying the function Add will give us a new function as output. That function itself takes 1 number as input and outputs yet another new function. That third function then takes 1 number as input and returns a number as output. As such:
Curry(Add); // returns a function f2 as output
// f2 takes 1 number as input and returns a function f3 as output
// i.e. f2(number) = f3
// f3 takes 1 number as input and returns a number as output
// i.e. f3(number) = number
So we can do this:
f2 = Curry(Add);
f3 = f2(7);
f3(5); // returns 12
In other words, "currying" and "partial application" are two totally different functions. Currying takes exactly 1 input, whereas partial application takes 2 (or more) inputs.
Even though they both return a function as output, the returned functions are of totally different forms as demonstrated above.
Note: this was taken from F# Basics an excellent introductory article for .NET developers getting into functional programming.
Currying means breaking a function with many arguments into a series
of functions that each take one argument and ultimately produce the
same result as the original function. Currying is probably the most
challenging topic for developers new to functional programming, particularly because it
is often confused with partial application. You can see both at work
in this example:
let multiply x y = x * y
let double = multiply 2
let ten = double 5
Right away, you should see behavior that is different from most
imperative languages. The second statement creates a new function
called double by passing one argument to a function that takes two.
The result is a function that accepts one int argument and yields the
same output as if you had called multiply with x equal to 2 and y
equal to that argument. In terms of behavior, it’s the same as this
code:
let double2 z = multiply 2 z
Often, people mistakenly say that multiply is curried to form double.
But this is only somewhat true. The multiply function is curried, but
that happens when it is defined because functions in F# are curried by
default. When the double function is created, it’s more accurate to
say that the multiply function is partially applied.
The multiply function is really a series of two functions. The first
function takes one int argument and returns another function,
effectively binding x to a specific value. This function also accepts
an int argument that you can think of as the value to bind to y. After
calling this second function, x and y are both bound, so the result is
the product of x and y as defined in the body of double.
To create double, the first function in the chain of multiply
functions is evaluated to partially apply multiply. The resulting
function is given the name double. When double is evaluated, it uses
its argument along with the partially applied value to create the
result.
Interesting question. After a bit of searching, "Partial Function Application is not currying" gave the best explanation I found. I can't say that the practical difference is particularly obvious to me, but then I'm not an FP expert...
Another useful-looking page (which I confess I haven't fully read yet) is "Currying and Partial Application with Java Closures".
It does look like this is widely-confused pair of terms, mind you.
I have answered this in another thread https://stackoverflow.com/a/12846865/1685865 . In short, partial function application is about fixing some arguments of a given multivariable function to yield another function with fewer arguments, while Currying is about turning a function of N arguments into a unary function which returns a unary function...[An example of Currying is shown at the end of this post.]
Currying is mostly of theoretical interest: one can express computations using only unary functions (i.e. every function is unary). In practice and as a byproduct, it is a technique which can make many useful (but not all) partial functional applications trivial, if the language has curried functions. Again, it is not the only means to implement partial applications. So you could encounter scenarios where partial application is done in other way, but people are mistaking it as Currying.
(Example of Currying)
In practice one would not just write
lambda x: lambda y: lambda z: x + y + z
or the equivalent javascript
function (x) { return function (y){ return function (z){ return x + y + z }}}
instead of
lambda x, y, z: x + y + z
for the sake of Currying.
Currying is a function of one argument which takes a function f and returns a new function h. Note that h takes an argument from X and returns a function that maps Y to Z:
curry(f) = h
f: (X x Y) -> Z
h: X -> (Y -> Z)
Partial application is a function of two(or more) arguments which takes a function f and one or more additional arguments to f and returns a new function g:
part(f, 2) = g
f: (X x Y) -> Z
g: Y -> Z
The confusion arises because with a two-argument function the following equality holds:
partial(f, a) = curry(f)(a)
Both sides will yield the same one-argument function.
The equality is not true for higher arity functions because in this case currying will return a one-argument function, whereas partial application will return a multiple-argument function.
The difference is also in the behavior, whereas currying transforms the whole original function recursively(once for each argument), partial application is just a one step replacement.
Source: Wikipedia Currying.
Simple answer
Curry: lets you call a function, splitting it in multiple calls, providing one argument per-call.
Partial: lets you call a function, splitting it in multiple calls, providing multiple arguments per-call.
Simple hints
Both allow you to call a function providing less arguments (or, better, providing them cumulatively). Actually both of them bind (at each call) a specific value to specific arguments of the function.
The real difference can be seen when the function has more than 2 arguments.
Simple e(c)(sample)
(in Javascript)
We want to run the following process function on different subjects (e.g. let's say our subjects are "subject1" and "foobar" strings):
function process(context, successCallback, errorCallback, subject) {...}
why always passing the arguments, like context and the callbacks, if they will be always the same?
Just bind some values for the the function:
processSubject = _.partial(process, my_context, my_success, my_error)
// assign fixed values to the first 3 arguments of the `process` function
and call it on subject1 and foobar, omitting the repetition of the first 3 arguments, with:
processSubject('subject1');
processSubject('foobar');
Comfy, isn't it? 😉
With currying you'd instead need to pass one argument per time
curriedProcess = _.curry(process); // make the function curry-able
processWithBoundedContext = curriedProcess(my_context);
processWithCallbacks = processWithBoundedContext(my_success)(my_error); // note: these are two sequential calls
result1 = processWithCallbacks('subject1');
// same as: process(my_context, my_success, my_error, 'subject1');
result2 = processWithCallbacks('foobar');
// same as: process(my_context, my_success, my_error, 'foobar');
Disclaimer
I skipped all the academic/mathematical explanation. Cause I don't know it. Maybe it helped 🙃
EDIT:
As added by #basickarl, a further slight difference in use of the two functions (see Lodash for examples) is that:
partial returns a pre-cooked function that can be called once with the missing argument(s) and return the final result;
while curry is being called multiple times (one for each argument), returning a pre-cooked function each time; except in the case of calling with the last argument, that will return the actual result from the processing of all the arguments.
With ES6:
here's a quick example of how immediate Currying and Partial-application are in ECMAScript 6.
const partialSum = math => (eng, geo) => math + eng + geo;
const curriedSum = math => eng => geo => math + eng + geo;
The difference between curry and partial application can be best illustrated through this following JavaScript example:
function f(x, y, z) {
return x + y + z;
}
var partial = f.bind(null, 1);
6 === partial(2, 3);
Partial application results in a function of smaller arity; in the example above, f has an arity of 3 while partial only has an arity of 2. More importantly, a partially applied function would return the result right away upon being invoke, not another function down the currying chain. So if you are seeing something like partial(2)(3), it's not partial application in actuality.
Further reading:
Functional Programming in 5 minutes
Currying: Contrast with Partial Function Application
I had this question a lot while learning and have since been asked it many times. The simplest way I can describe the difference is that both are the same :) Let me explain...there are obviously differences.
Both partial application and currying involve supplying arguments to a function, perhaps not all at once. A fairly canonical example is adding two numbers. In pseudocode (actually JS without keywords), the base function may be the following:
add = (x, y) => x + y
If I wanted an "addOne" function, I could partially apply it or curry it:
addOneC = curry(add, 1)
addOneP = partial(add, 1)
Now using them is clear:
addOneC(2) #=> 3
addOneP(2) #=> 3
So what's the difference? Well, it's subtle, but partial application involves supplying some arguments and the returned function will then execute the main function upon next invocation whereas currying will keep waiting till it has all the arguments necessary:
curriedAdd = curry(add) # notice, no args are provided
addOne = curriedAdd(1) # returns a function that can be used to provide the last argument
addOne(2) #=> returns 3, as we want
partialAdd = partial(add) # no args provided, but this still returns a function
addOne = partialAdd(1) # oops! can only use a partially applied function once, so now we're trying to add one to an undefined value (no second argument), and we get an error
In short, use partial application to prefill some values, knowing that the next time you call the method, it will execute, leaving undefined all unprovided arguments; use currying when you want to continually return a partially-applied function as many times as necessary to fulfill the function signature. One final contrived example:
curriedAdd = curry(add)
curriedAdd()()()()()(1)(2) # ugly and dumb, but it works
partialAdd = partial(add)
partialAdd()()()()()(1)(2) # second invocation of those 7 calls fires it off with undefined parameters
Hope this helps!
UPDATE: Some languages or lib implementations will allow you to pass an arity (total number of arguments in final evaluation) to the partial application implementation which may conflate my two descriptions into a confusing mess...but at that point, the two techniques are largely interchangeable.
For me partial application must create a new function where the used arguments are completely integrated into the resulting function.
Most functional languages implement currying by returning a closure: do not evaluate under lambda when partially applied. So, for partial application to be interesting, we need to make a difference between currying and partial application and consider partial application as currying plus evaluation under lambda.
I could be very wrong here, as I don't have a strong background in theoretical mathematics or functional programming, but from my brief foray into FP, it seems that currying tends to turn a function of N arguments into N functions of one argument, whereas partial application [in practice] works better with variadic functions with an indeterminate number of arguments. I know some of the examples in previous answers defy this explanation, but it has helped me the most to separate the concepts. Consider this example (written in CoffeeScript for succinctness, my apologies if it confuses further, but please ask for clarification, if needed):
# partial application
partial_apply = (func) ->
args = [].slice.call arguments, 1
-> func.apply null, args.concat [].slice.call arguments
sum_variadic = -> [].reduce.call arguments, (acc, num) -> acc + num
add_to_7_and_5 = partial_apply sum_variadic, 7, 5
add_to_7_and_5 10 # returns 22
add_to_7_and_5 10, 11, 12 # returns 45
# currying
curry = (func) ->
num_args = func.length
helper = (prev) ->
->
args = prev.concat [].slice.call arguments
return if args.length < num_args then helper args else func.apply null, args
helper []
sum_of_three = (x, y, z) -> x + y + z
curried_sum_of_three = curry sum_of_three
curried_sum_of_three 4 # returns a function expecting more arguments
curried_sum_of_three(4)(5) # still returns a function expecting more arguments
curried_sum_of_three(4)(5)(6) # returns 15
curried_sum_of_three 4, 5, 6 # returns 15
This is obviously a contrived example, but notice that partially applying a function that accepts any number of arguments allows us to execute a function but with some preliminary data. Currying a function is similar but allows us to execute an N-parameter function in pieces until, but only until, all N parameters are accounted for.
Again, this is my take from things I've read. If anyone disagrees, I would appreciate a comment as to why rather than an immediate downvote. Also, if the CoffeeScript is difficult to read, please visit coffeescript.org, click "try coffeescript" and paste in my code to see the compiled version, which may (hopefully) make more sense. Thanks!
I'm going to assume most people who ask this question are already familiar with the basic concepts so their is no need to talk about that. It's the overlap that is the confusing part.
You might be able to fully use the concepts, but you understand them together as this pseudo-atomic amorphous conceptual blur. What is missing is knowing where the boundary between them is.
Instead of defining what each one is, it's easier to highlight just their differences—the boundary.
Currying is when you define the function.
Partial Application is when you call the function.
Application is math-speak for calling a function.
Partial application requires calling a curried function and getting a function as the return type.
A lot of people here do not address this properly, and no one has talked about overlaps.
Simple answer
Currying: Lets you call a function, splitting it in multiple calls, providing one argument per-call.
Partial Application: Lets you call a function, splitting it in multiple calls, providing multiple arguments per-call.
One of the significant differences between the two is that a call to a
partially applied function returns the result right away, not another
function down the currying chain; this distinction can be illustrated
clearly for functions whose arity is greater than two.
What does that mean? That means that there are max two calls for a partial function. Currying has as many as the amount of arguments. If the currying function only has two arguments, then it is essentially the same as a partial function.
Examples
Partial Application and Currying
function bothPartialAndCurry(firstArgument) {
return function(secondArgument) {
return firstArgument + secondArgument;
}
}
const partialAndCurry = bothPartialAndCurry(1);
const result = partialAndCurry(2);
Partial Application
function partialOnly(firstArgument, secondArgument) {
return function(thirdArgument, fourthArgument, fifthArgument) {
return firstArgument + secondArgument + thirdArgument + fourthArgument + fifthArgument;
}
}
const partial = partialOnly(1, 2);
const result = partial(3, 4, 5);
Currying
function curryOnly(firstArgument) {
return function(secondArgument) {
return function(thirdArgument) {
return function(fourthArgument ) {
return function(fifthArgument) {
return firstArgument + secondArgument + thirdArgument + fourthArgument + fifthArgument;
}
}
}
}
}
const curryFirst = curryOnly(1);
const currySecond = curryFirst(2);
const curryThird = currySecond(3);
const curryFourth = curryThird(4);
const result = curryFourth(5);
// or...
const result = curryOnly(1)(2)(3)(4)(5);
Naming conventions
I'll write this when I have time, which is soon.
There are other great answers here but I believe this example (as per my understanding) in Java might be of benefit to some people:
public static <A,B,X> Function< B, X > partiallyApply( BiFunction< A, B, X > aBiFunction, A aValue ){
return b -> aBiFunction.apply( aValue, b );
}
public static <A,X> Supplier< X > partiallyApply( Function< A, X > aFunction, A aValue ){
return () -> aFunction.apply( aValue );
}
public static <A,B,X> Function< A, Function< B, X > > curry( BiFunction< A, B, X > bif ){
return a -> partiallyApply( bif, a );
}
So currying gives you a one-argument function to create functions, where partial-application creates a wrapper function that hard codes one or more arguments.
If you want to copy&paste, the following is noisier but friendlier to work with since the types are more lenient:
public static <A,B,X> Function< ? super B, ? extends X > partiallyApply( final BiFunction< ? super A, ? super B, X > aBiFunction, final A aValue ){
return b -> aBiFunction.apply( aValue, b );
}
public static <A,X> Supplier< ? extends X > partiallyApply( final Function< ? super A, X > aFunction, final A aValue ){
return () -> aFunction.apply( aValue );
}
public static <A,B,X> Function< ? super A, Function< ? super B, ? extends X > > curry( final BiFunction< ? super A, ? super B, ? extends X > bif ){
return a -> partiallyApply( bif, a );
}
In writing this, I confused currying and uncurrying. They are inverse transformations on functions. It really doesn't matter what you call which, as long as you get what the transformation and its inverse represent.
Uncurrying isn't defined very clearly (or rather, there are "conflicting" definitions that all capture the spirit of the idea). Basically, it means turning a function that takes multiple arguments into a function that takes a single argument. For example,
(+) :: Int -> Int -> Int
Now, how do you turn this into a function that takes a single argument? You cheat, of course!
plus :: (Int, Int) -> Int
Notice that plus now takes a single argument (that is composed of two things). Super!
What's the point of this? Well, if you have a function that takes two arguments, and you have a pair of arguments, it is nice to know that you can apply the function to the arguments, and still get what you expect. And, in fact, the plumbing to do it already exists, so that you don't have to do things like explicit pattern matching. All you have to do is:
(uncurry (+)) (1,2)
So what is partial function application? It is a different way to turn a function in two arguments into a function with one argument. It works differently though. Again, let's take (+) as an example. How might we turn it into a function that takes a single Int as an argument? We cheat!
((+) 0) :: Int -> Int
That's the function that adds zero to any Int.
((+) 1) :: Int -> Int
adds 1 to any Int. Etc. In each of these cases, (+) is "partially applied".
Currying
Wikipedia says
Currying is the technique of converting a function that takes multiple arguments into a sequence of functions that each takes a single argument.
Example
const add = (a, b) => a + b
const addC = (a) => (b) => a + b // curried function. Where C means curried
Partial application
Article Just Enough FP: Partial Application
Partial application is the act of applying some, but not all, of the arguments to a function and returning a new function awaiting the rest of the arguments. These applied arguments are stored in closure and remain available to any of the partially applied returned functions in the future.
Example
const add = (a) => (b) => a + b
const add3 = add(3) // add3 is a partially applied function
add3(5) // 8
The difference is
currying is a technique (pattern)
partial application is a function with some predefined arguments (like add3 from the previous example)
I've been working for some time on a Javascript FP library called Ramda, and I'm having a slight problem with naming things. (You've heard the old line, right? "There are only two hard problems in Computer Science: cache invalidation, naming things, and off-by-one errors.")
In this library, (almost) every function of more than one parameter is automatically curried. And this works well for most use-cases. But there are some issues with a few functions which are non-commutative binary operators. The issue is that the English names often tend to imply something different than what happens when currying is applied. For example,
var div10 = divide(10);
sounds like it should be a function that divides its parameter by 10. But in fact it divides its parameter into 10, which is pretty clear if you look at the definition:
var divide = curry(function(a, b) {
return a / b;
});
So instead the expected:
div10(50); //=> 5 // NO!!
In fact, you get
div10(50); //=> 0.2 // Correct, but surprising!
We handle this by documenting the difference from people's possible expectations, and creating divideBy, which is just flip(divide) and subtractN, which is flip(subtract). But we haven't found a good equivalent for functions such as lt:
R.lt = curry(function(a, b) {
return a < b;
});
or its cousins lte, gt, and gte.
My own intuition would be that
map(lt(5), [8, 6, 7, 5, 3, 0, 9]);
//=> [false, false, false, false, true, true, false]
But of course, it actually returns
//=> [true, true, true, false, false, false, true]
So I'd like to do the same document-and-point-to-alternate-name routine for lt and its ilk. But I haven't been able to find a good name. The only real candidate has been ltVal and that doesn't really work when called with both arguments. We did discuss this issue, but had no good conclusions.
Have others dealt with this and come up with good solutions? Or even if not, any good suggestions for a name for the flipped versions of these functions?
Update
Someone suggested that this be closed because 'unclear what you were asking', and I guess the question really was lost a bit in the explanation. The simple question is:
What would be a good, intuitive name for a flipped version of lt?
First of all, kudos on the functional programming library that you are maintaining. I've always wanted to write one myself, but I've never found the time to do so.
Considering the fact that you are writing a functional programming library I'm going to assume that you know about Haskell. In Haskell we have functions and operators. Functions are always prefix. Operators are always infix.
Functions in Haskell can be converted into operators using backticks. For example div 6 3 can be written as 6 `div` 3. Similarly operators can be converted into functions using parentheses. For example 2 < 3 can be written as (<) 2 3.
Operators can also be partially applied using sections. There are two types of sections: left sections (e.g. (2 <) and (6 `div`)) and right sections (e.g. (< 3) and (`div` 3)). Left sections are translated as follows: (2 <) becomes (<) 2. Right sections: (< 3) becomes flip (<) 3.
In JavaScript we only have functions. There is no “good” way to create operators in JavaScript. You can write code like (2).lt(3), but in my humble opinion it is uncouth and I would strongly advise against writing code like that.
So trivially we can write normal functions and operators as functions:
div(6, 3) // normal function: div 6 3
lt(2, 3) // operator as a function: (<) 2 3
Writing and implementing infix operators in JavaScript is a pain. Hence we won't have the following:
(6).div(3) // function as an operator: 6 `div` 3
(2).lt(3) // normal operator: 2 < 3
However sections are important. Let's start with the right section:
div(3) // right section: (`div` 3)
lt(3) // right section: (< 3)
When I see div(3) I would expect it to be a right section (i.e. it should behave as (`div` 3)). Hence, according to the principle of least astonishment, this is the way it should be implemented.
Now comes the question of left sections. If div(3) is a right section then what should a left section look like? In my humble opinion it should look like this:
div(6, _) // left section: (6 `div`)
lt(2, _) // left section: (2 <)
To me this reads as “divide 6 by something” and “is 2 lesser than something?” I prefer this way because it is explicit. According to The Zen of Python, “Explicit is better than implicit.”
So how does this affect existing code? For example, consider the filter function. To filter the odd numbers in a list we would write filter(odd, list). For such a function does currying work as expected? For example, how would we write a filterOdd function?
var filterOdd = filter(odd); // expected solution
var filterOdd = filter(odd, _); // left section, astonished?
According to the principle of least astonishment it should simply be filter(odd). The filter function is not meant to be used as an operator. Hence the programmer should not be forced to use it as a left section. There should be a clear distinction between functions and “function operators”.
Fortunately distinguishing between functions and function operators is pretty intuitive. For example, the filter function is clearly not a function operator:
filter odd list -- filter the odd numbers from the list; makes sense
odd `filter` list -- odd filter of list? huh?
On the other hand the elem function is clearly a function operator:
list `elem` n -- element n of the list; makes sense
elem list n -- element list, n? huh?
It's important to note that this distinction is only possible because functions and function operators are mutually exclusive. It stands to reason that given a function it may either be a normal function or else a function operator, but not both.
It's interesting to note that given a binary function if you flip its arguments then it becomes a binary operator and vice versa. For example consider the flipped variants of filter and elem:
list `filter` odd -- now filter makes sense an an operator
elem n list -- now elem makes sense as a function
In fact this could be generalized for any n-arity function were n is greater than 1. You see, every function has a primary argument. Trivially, for unary functions this distinction is irrelevant. However for non-unary functions this distinction is important.
If the primary argument of the function comes at the end of the argument list then the function is a normal function (e.g. filter odd list where list is the primary argument). Having the primary argument at the end of the list is necessary for function composition.
If the primary argument of the function comes at the beginning of the argument list then the function is a function operator (e.g. list `elem` n where list is the primary argument).
Operators are analogous to methods in OOP and the primary argument is analogous to the object of the method. For example list `elem` n would be written as list.elem(n) in OOP. Chaining methods in OOP is analogous to function composition chains in FP[1].
The primary argument of the function may only be either at the beginning or at the end of the argument list. It wouldn't make sense for it to be anywhere else. This property is vacuously true for binary functions. Hence flipping binary functions makes them operators and vice-versa.
The rest of the arguments along with the function form an indivisible atom called the stem of the argument list. For example in filter odd list the stem is filter odd. In list `elem` n the stem is (`elem` n).
The order and the elements of the stem must remain unchanged for the expression to make sense. This is why odd `filter` list and elem list n don't make any sense. However list `filter` odd and elem n list make sense because the stem is unchanged.
Coming back to the main topic, since functions and function operators are mutually exclusive you could simply treat function operators differently than the way you treat normal functions.
We want operators to have the following behavior:
div(6, 3) // normal operator: 6 `div` 3
div(6, _) // left section: (6 `div`)
div(3) // right section: (`div` 3)
We want to define operators as follows:
var div = op(function (a, b) {
return a / b;
});
The definition of the op function is simple:
function op(f) {
var length = f.length, _; // we want underscore to be undefined
if (length < 2) throw new Error("Expected binary function.");
var left = R.curry(f), right = R.curry(R.flip(f));
return function (a, b) {
switch (arguments.length) {
case 0: throw new Error("No arguments.");
case 1: return right(a);
case 2: if (b === _) return left(a);
default: return left.apply(null, arguments);
}
};
}
The op function is similar to using backticks to convert a function into a operator in Haskell. Hence you could add it as a standard library function for Ramda. Also mention in the docs that the primary argument of an operator should be the first argument (i.e. it should look like OOP, not FP).
[1] On a side note it would be awesome if Ramda allowed you to compose functions as though it was chaining methods in regular JavaScript (e.g. foo(a, b).bar(c) instead of compose(bar(c), foo(a, b))). It's difficult, but doable.
We all know that naming in programming is serious business, particularly when it comes to functions in curried form. It is a valid solution to handle this issue with a programmatic approach as Aadit did in his response. However, I see two issues with his implementation:
it introduces function operators with left/right sections in Javascript, which are not part of the language
it requires a hideous placeholder or undefined hack to achieve that
Javascript has no curried operators and thus no left or right sections. An idiomatic Javascript solution should consider that.
The cause of the problem
Curried functions don't have a notion of arity, because every function invocation requires exactly one argument. You can either partially or completely apply curried functions without any helpers:
const add = y => x => x + y;
const add2 = add(2); // partial application
add(2)(3); // complete application
Usually the last argument of a function is its primarily one, because it is passed through function compositions (similar to objects that allow method chaining). Consequently when you partially apply a function, you want to pass its initial arguments:
const comp = f => g => x => f(g(x));
const map = f => xs => xs.map(x => f(x));
const inc = x => x + 1;
const sqr = x => x * x;
comp(map(inc)) (map(sqr)) ([1,2,3]); // [2,5,10]
Operator functions are special in this regard. They are binary functions that reduce their two arguments to a single return value. Since not every operator is commutative (a - b !== b - a) the argument order matters. For this reason operator functions don't have a primarily argument. But people are accustomed to read expressions with them in a certain way depending on the type of application:
const concat = y => xs => xs.concat(y);
const sub = y => x => x - y;
// partial application:
const concat4 = concat(4);
const sub4 = sub(4);
concat4([1,2,3]); // [1,2,3,4] - OK
sub4(3); // -1 - OK
// complete application:
concat([1,2,3]) (4); // [4,1,2,3] - ouch!
sub(4) (3); // -1 - ouch!
We defined concat and sub with flipped arguments, so that partial application works as expected. This evidently doesn't apply to complete application though.
A manual solution
const flip = f => y => x => f(x) (y);
const concat_ = flip(concat);
const sub_ = flip(sub);
concat_(xs) (4); // [1,2,3,4] - OK
sub_(4) (3); // 1 - OK
concat_ and sub_ correspond to left sections in Haskell. Please note that function operators like add or lt don't need a left section version because the former are commutative and the latter are predicates, which have logical counterparts:
const comp2 = f => g => x => y => f(g(x) (y));
const map = f => xs => xs.map(x => f(x));
const flip = f => y => x => f(x) (y);
const not = x => !x;
const notf2 = comp2(not);
const lt = y => x => x < y;
const gt = flip(lt);
const lte = notf2(gt);
const gte = notf2(lt);
map(lt(5)) ([8, 6, 7, 5, 3, 0, 9]);
// [false, false, false, false, true, true, false]
map(gte(5)) ([8, 6, 7, 5, 3, 0, 9]);
// [true, true, true, true, false, false, true]
Conclusion
We should solve this naming issue rather with a naming convention then with a programmatic solution which extends Javascript in a non-idiomatic way. Naming conventions are not ideal...well, just like Javascript.
I'm working in a language that translates to JavaScript. In order to avoid some stack overflows, I'm applying tail call optimization by converting certain functions to for loops. What is surprising is that the conversion is not faster than the recursive version.
http://jsperf.com/sldjf-lajf-lkajf-lkfadsj-f/5
Recursive version:
(function recur(a0,s0){
return a0==0 ? s0 : recur(a0-1, a0+s0)
})(10000,0)
After tail call optimization:
ret3 = void 0;
a1 = 10000;
s2 = 0;
(function(){
while (!ret3) {
a1 == 0
? ret3 = s2
: (a1_tmp$ = a1 - 1 ,
s2_tmp$ = a1 + s2,
a1 = a1_tmp$,
s2 = s2_tmp$);
}
})();
ret3;
After some cleanup using Google Closure Compiler:
ret3 = 0;
a1 = 1E4;
for(s2 = 0; ret3 == 0;)
0 == a1
? ret3 = s2
: (a1_tmp$ = a1 - 1 ,
s2_tmp$ = a1 + s2,
a1 = a1_tmp$,
s2 = s2_tmp$);
c=ret3;
The recursive version is faster than the "optimized" ones! How can this be possible, if the recursive version has to handle thousands of context changes?
There's more to optimising than tail-call optimisation.
For instance, I notice you're using two temporary variables, when all you need is:
s2 += a1;
a1--;
This alone practically reduces the number of operations by a third, resulting in a performance increase of 50%
In the long run, it's important to optimise what operations are being performed before trying to optimise the operations themselves.
EDIT: Here's an updated jsperf
as Kolink say what your piece of code do is simply adding n to the total, reduce n by 1, and loop until n not reach 0
so just do that :
n = 10000, o = 0; while(n) o += n--;
it's more faster and lisible than the recursive version, and off course output the same result
There are not so much context changes inside the recursive version as you expect, since the named function recur is contained in the scope of recur itself/they share the same scope. The reason for that has to do with the way the JavaScript engines evaluate scope, and there are plenty of websites out there which explain this topic, so I will not do it here. At a second look you will notice that recur is also a so called "pure" function, which basically means it never has to leave it's own scope as long as the internal execution runs (simply put: until it returns a value). These two facts make it basically fast. I just want to mention here, the first example is the only tail call optimized one of all three – a tc optimization can only be done in recursive functions and this is the only recursive one.
However, a second look at the second example (no pun intended) reveals, that the "optimizer" made things worse for you, since it introduced scopes into the former pure function by splitting the operation into
variables instead of arguments
a while loop
a IIFE (immediatly invoked function expression) that separates the introduced inner and outer variables
Which leads to poorer performance since now the engine has to handle 10000 context changes.
To tell you the truth I do not know why the third example is poorer in performance than the recursive one, so maybe it has to do with:
the browser you use (ever tried another one and compared the results?)
the number of variables
stack frames created by for-loops (never heard of though), which
would have to do with the first example: the JS engines interpret a
pure recursive function until it finds a return statement. If the last thing following the statement is a function call, then evaluate any expressions (if any) and variables to pass as arguments, call the function and throw away the frame
something, only the browser-vendors can truly tell you :)