
Problem Statement
Given a function fn
, the task is to return a curried version of that function. Currying is a transformation of functions that translates a function from callable as f(a, b, c)
into callable as f(a)(b)(c)
. Essentially, it breaks down a function that takes multiple arguments into a series of functions that each take only one argument.
For example, consider a function sum
that calculates the sum of three numbers:
function sum(a, b, c) {
return a + b + c;
}
The curried version of sum
, let's say curriedSum
, can be executed as curriedSum(1)(2)(3)
, curriedSum(1, 2)(3)
, or even curriedSum(1)(2, 3)
. Each of these calls would yield the same result as the original sum(1, 2, 3)
call, demonstrating the flexibility of curried functions to receive the same total number of arguments through multiple calls.
Examples
Example 1
Input:
fn = function sum(a, b, c) { return a + b + c; } inputs = [[1],[2],[3]]
Output:
6
Explanation:
The code being executed is: const curriedSum = curry(fn); curriedSum(1)(2)(3) === 6; curriedSum(1)(2)(3) should return the same value as sum(1, 2, 3).
Example 2
Input:
fn = function sum(a, b, c) { return a + b + c; } inputs = [[1,2],[3]]
Output:
6
Explanation:
curriedSum(1, 2)(3) should return the same value as sum(1, 2, 3).
Example 3
Input:
fn = function sum(a, b, c) { return a + b + c; } inputs = [[],[],[1,2,3]]
Output:
6
Explanation:
You should be able to pass the parameters in any way, including all at once or none at all. curriedSum()()(1, 2, 3) should return the same value as sum(1, 2, 3).
Example 4
Input:
fn = function life() { return 42; } inputs = [[]]
Output:
42
Explanation:
currying a function that accepts zero parameters should effectively do nothing. curriedLife() === 42
Constraints
1 <= inputs.length <= 1000
0 <= inputs[i][j] <= 105
0 <= fn.length <= 1000
inputs.flat().length == fn.length
- function parameters explicitly defined
- If
fn.length > 0
then the last array ininputs
is not empty - If
fn.length === 0
theninputs.length === 1
Approach and Intuition
To tackle this problem, understanding the examples and constraints leads to devising the right approach.
Intuition
The fundamental goal of currying a function is to break down a multi-argument function into a series of unary (single-argument) functions. Each unary function returns another function, expecting the next argument, until all arguments have been received, at which point the original function's result is computed and returned.
Examples
Example 1
Input:
fn = function sum(a, b, c) { return a + b + c; } inputs = [[1],[2],[3]]
Output:
6
Explanation:
The code being executed is: const curriedSum = curry(fn); curriedSum(1)(2)(3) === 6; curriedSum(1)(2)(3) should return the same value as sum(1, 2, 3).
Example 2
Input:
fn = function sum(a, b, c) { return a + b + c; } inputs = [[1,2],[3]]
Output:
6
Explanation:
curriedSum(1, 2)(3) should return the same value as sum(1, 2, 3).
Example 3
Input:
fn = function sum(a, b, c) { return a + b + c; } inputs = [[],[],[1,2,3]]
Output:
6
Explanation:
You should be able to pass the parameters in any way, including all at once or none at all. curriedSum()()(1, 2, 3) should return the same value as sum(1, 2, 3).
Example 4
Input:
fn = function life() { return 42; } inputs = [[]]
Output:
42
Explanation:
currying a function that accepts zero parameters should effectively do nothing. curriedLife() === 42
Constraints
1 <= inputs.length <= 1000
0 <= inputs[i][j] <= 105
0 <= fn.length <= 1000
inputs.flat().length == fn.length
- function parameters explicitly defined
- If
fn.length > 0
then the last array ininputs
is not empty - If
fn.length === 0
theninputs.length === 1
Approach Based on Examples
Example 1:
- Input:
fn = sum(a, b, c)
andinputs = [[1], [2], [3]]
- Here, the curried function separates each argument into its function call:
curriedSum(1)(2)(3)
. - The final result after passing all arguments separately is 6, identical to
sum(1, 2, 3)
.
- Input:
Example 2:
- Input:
inputs = [[1,2],[3]]
- This demonstrates partial application where the first curried function takes multiple arguments in one go:
curriedSum(1, 2)(3)
. - The result remains the same as passing all arguments at once.
- Input:
Example 3:
- Input:
inputs = [[],[],[1,2,3]]
- Illustrates that the curried function should handle calls with no arguments initially and still function correctly when all arguments passed later:
curriedSum()()(1, 2, 3)
. - This flexibility in handling input is key in a curried function.
- Input:
Example 4:
- Input:
fn = function life() { return 42; }
- Even without any parameters, currying should not alter the behavior or result of the function, indicating
curriedLife()
should still return 42.
- Input:
These outlined steps from the examples demonstrate the essential characteristic of currying: flexibility in how input is received while guaranteeing the output remains consistent with the original function's behavior given the same total input.
Solutions
- JavaScript
var curryFunction = function(func) {
return function curriedFunc(...params) {
if (params.length >= func.length) {
return func.apply(this, params);
}
return curriedFunc.bind(this, ...params);
};
};
The provided JavaScript code defines a function named curryFunction
designed to transform a given function into its curried version. Currying is a technique where a function with multiple arguments is transformed into a sequence of nested functions, each taking a single argument. This allows for partial function application.
- The
curryFunction
takesfunc
as an argument, which is the function to be curried. - Inside, it returns a new function
curriedFunc
. This nested function accumulates parameters passed to it (...params
). - Check if the number of parameters provided is at least equal to the expected number of parameters (
func.length
). If true, it calls the original functionfunc
usingapply
to pass the collected parameters. - If the accumulated parameters are insufficient,
curriedFunc
usesbind
to create a new function, pre-filled with the collected parameters for the next call.
This approach maximizes flexibility and reusability in functional programming, allowing you to create more specific functions from general ones by fixing some arguments ahead of time.
No comments yet.