How to uncurry a function up to depth n in JavaScript?

In JavaScript, a function is considered "curried" if it takes one or more arguments and returns a new function that expects the remaining arguments. Currying is a powerful technique that can be used to create new functions from existing ones, or to "uncurry" a function up to depth n.

Why do we uncurry a function?

There are several reasons why you might want to uncurry a function. For example, you may want to ?

  • Use a curried function in a context where a non-curried function is expected

  • Convert a curried function to a non-curried form to make it easier to read or debug

  • Optimize a curried function for performance

Understanding Currying First

Before uncurrying, let's see a basic curried function:

<!DOCTYPE html>
<html>
<head>
    <title>Curried Function Example</title>
</head>
<body>
    <div id="result1"></div>
    <script>
        // Curried function - takes one argument at a time
        function curriedAdd(a) {
            return function(b) {
                return function(c) {
                    return a + b + c;
                }
            }
        }
        
        // Using the curried function
        let result = curriedAdd(1)(2)(3);
        document.getElementById("result1").innerHTML = "Curried result: " + result;
    </script>
</body>
</html>
Curried result: 6

Method 1: Using Function.prototype.apply

The "Function.prototype.apply" method can be used to uncurry a function up to depth n. Here's how to create an uncurried version:

<!DOCTYPE html>
<html>
<head>
    <title>Uncurry with Apply</title>
</head>
<body>
    <div id="result2"></div>
    <script>
        // Original curried function
        function curriedAdd(a) {
            return function(b) {
                return a + b;
            }
        }
        
        // Uncurry function using apply
        function uncurry(fn) {
            return function(...args) {
                return args.reduce((acc, arg) => acc(arg), fn);
            };
        }
        
        // Create uncurried version
        let uncurriedAdd = uncurry(curriedAdd);
        
        // Use it with multiple arguments at once
        let result = uncurriedAdd(5, 3);
        document.getElementById("result2").innerHTML = "Uncurried result: " + result;
    </script>
</body>
</html>
Uncurried result: 8

Method 2: Manual Uncurrying to Specific Depth

You can manually uncurry a function to a specific depth by creating a wrapper function:

<!DOCTYPE html>
<html>
<head>
    <title>Manual Uncurrying</title>
</head>
<body>
    <div id="result3"></div>
    <script>
        // Curried function with depth 3
        function curriedMultiply(a) {
            return function(b) {
                return function(c) {
                    return a * b * c;
                }
            }
        }
        
        // Uncurry to depth 3
        function uncurryToDepth3(fn) {
            return function(a, b, c) {
                return fn(a)(b)(c);
            };
        }
        
        // Create uncurried version
        let uncurriedMultiply = uncurryToDepth3(curriedMultiply);
        
        // Use with all arguments at once
        let result = uncurriedMultiply(2, 3, 4);
        document.getElementById("result3").innerHTML = "Uncurried multiply result: " + result;
    </script>
</body>
</html>
Uncurried multiply result: 24

Generic Uncurry Function

Here's a more flexible approach that can handle any depth:

<!DOCTYPE html>
<html>
<head>
    <title>Generic Uncurry Function</title>
</head>
<body>
    <div id="result4"></div>
    <script>
        // Generic uncurry function
        function uncurryN(fn, n) {
            return function(...args) {
                if (args.length >= n) {
                    let result = fn;
                    for (let i = 0; i < n; i++) {
                        result = result(args[i]);
                    }
                    return result;
                }
                // Return partially applied function if not enough args
                return uncurryN(args.reduce((f, arg) => f(arg), fn), n - args.length);
            };
        }
        
        // Curried function
        function curriedSum(a) {
            return function(b) {
                return function(c) {
                    return function(d) {
                        return a + b + c + d;
                    }
                }
            }
        }
        
        // Uncurry to depth 4
        let uncurriedSum = uncurryN(curriedSum, 4);
        
        let result = uncurriedSum(1, 2, 3, 4);
        document.getElementById("result4").innerHTML = "Generic uncurry result: " + result;
    </script>
</body>
</html>
Generic uncurry result: 10

Comparison of Methods

Method Flexibility Performance Use Case
Manual Uncurry Limited Fast Known depth, simple functions
Generic Uncurry High Moderate Variable depth, reusable
Reduce-based High Good Dynamic argument handling

Conclusion

Uncurrying functions allows you to convert curried functions back to regular multi-argument functions. Use manual uncurrying for known depths or generic approaches for flexible solutions.

Updated on: 2026-03-15T23:19:00+05:30

266 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements