Function for adding numbers in Javascript with currying

Can you help me solve this interesting problem? I need a javascript function that can return the sum of all arguments passed to it, even when called multiple times.

I have identified different ways in which the function can be called -

sum(1, 2, 3, 4);
sum(1, 2)(3, 4);
sum(1, 2)(3)(4);
sum(1, 2, 3)(4);
sum(1)(2, 3, 4);

All these variations should work correctly and return the total of 10.

I have made an attempt at solving this issue, but my code only works for the first two function calls sum(1, 2, 3, 4) and sum(1, 2)(3, 4). It fails for the other cases.

const arr = [];

function sum(...args) {
  if (args.length === 4) {
    return args.reduce((acc, curr) => {
      return (acc = acc + curr);
    }, 0);
  } else {
    arr.push(...args);
    return function(...args) {
      arr.push(...args);
      return sum(...arr);
    };
  }
}

I would appreciate any assistance with this problem as it's really getting frustrating.

Thank you!

Answer №1

Great job, you're almost there. A clever way to approach this is by utilizing the .bind method to create a function that captures the initial arguments if less than four are provided.

Here's an example of how you can implement this:

function calculateTotal(...args) {
  if (args.length >= 4) {
    return args.reduce((acc, curr) => {
      return acc + curr;
    }, 0);
  } else {
    // Bind the available arguments and return the function:
    return calculateTotal.bind(null, ...args)
  }
}

console.log(calculateTotal(1, 2, 3, 4));
console.log(calculateTotal(1, 2)(3, 4));
console.log(calculateTotal(1, 2)(3)(4));
console.log(calculateTotal(1, 2, 3)(4));
console.log(calculateTotal(1)(2, 3, 4));

Additionally, consider updating the check condition to ensure it doesn't lead to infinite currying by changing to >= 4.

Answer №2

When it comes to currying, there is a specific behavior that doesn't always play nicely with variadic functions due to the uncertainty of arity. However, if you specify an arity in your problem (e.g., 4), it becomes possible to determine when to return a result.

const curryN = (n, f, ...xs) =>
  (...ys) =>
    ys.length >= n
      ? f(...xs, ...ys)
      : curryN(n - ys.length, f, ...xs, ...ys)
      
const add = (...numbers) =>
  numbers.reduce((a, b) => a + b, 0)
  
const curryAdd =
  curryN(4, add)
  
console.log(
  curryAdd(1)(2)(3)(4), // 10
  curryAdd(1, 2)(3, 4), // 10
  curryAdd(1, 2, 3)(4), // 10
  curryAdd(1)(2, 3, 4), // 10
  curryAdd(1, 2, 3, 4)  // 10
)

Although this approach can be fragile for designing programs and deviates from true currying that only accepts one argument per application, partial application offers a much more reliable behavior.

const partial = (f, ...xs) =>
  (...ys) =>
    f(...xs, ...ys)
    
const add = (...numbers) =>
  numbers.reduce((a, b) => a + b, 0)
  
console.log(
  partial(add, 1)(2, 3, 4), // 10
  partial(add, 1, 2)(3, 4), // 10
  partial(add, 1, 2, 3)(4)  // 10
)

Please refer to this related answer for further insights.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way I can retrieve my Nodemailer email and store it in a variable?

I am currently utilizing the nodemailer module in conjunction with node.js and have successfully implemented the following: let transporter = nodemailer.createTransport({ service: 'gmail', auth: { user: '<a href="/cdn-cgi/l/email ...

Have you ever wondered why the React HeroIcons architecture includes React.createElement instead of simply returning plain SVG elements?

As I integrate HeroIcons into my Next.Js app, I find myself pondering over how they have structured their package architecture. The way they return icons is like this: const React = require("react"); function ArchiveIcon(props, svgRef) { retur ...

"Incorporate information from a separate VueJs object to enhance your data analysis

Just a quick question here. I have an object with the following value: data() { return { nation: { CZ: require("../../../../../svg/czech-flag.svg"), } }; }, Then I have an API object (FYI, the API is working fine) doctor ...

Using jQuery to remove the td element from an HTML table

Hello everyone, I have a query. I am trying to remove a specific td from a table using JavaScript, but the remove() function is not working. Here is my code: $('.btnEliminarLicencia').off('click'); $('.btnEliminarLicencia&apo ...

Incorporating multiple colors into a div with jQuery: A guide

I am looking for a way to create a legend by merging a specified number of colors within a div. I came across this useful Sample code that I have referenced. $.each(Array(50), function() { $("<div>").appendTo(document.body); }); var divs = $(&a ...

Navigating through the Express Routing: Homepage and Error 404

I've been working on a Node application with Express, and currently have the following code snippet in my app: app.use('/', function(req, res) { res.render('index', {}); }); While this route is functioning properly ...

utilizing a pair of API requests within a personalized Alexa skill

I posted a question about integrating Alexa with the Steam custom skill API here, but I realize it might be too detailed for some to read through. In essence, my main question is: Can you make two separate API calls within the same block of JS code while ...

Passing Data to a Different Route in Vue.js

Being new to Vue.js, I have a question on how to efficiently handle data retrieval from my backend application. Here is the code snippet that fetches all the data: var app2 = new Vue({ delimiters: ['%%', '%%'], el: '#app2& ...

Using React.JS: Display Object Map in rendering

I have an object with family information that looks like this: Family: Parent0: BirthPlace: "dsa" Birthday: "2021-01-04" Relationship: "dsa" SurnameAndName: "dasdsa" Parent1: BirthPlace: & ...

Tips for creating a more seamless box transition within HTML

I've been searching for information on this topic, but I haven't been able to find a satisfactory answer. I want to create a div that displays "Contact Us" and when clicked, smoothly reveals a layer with input fields. I know I can use JavaScri ...

Launch a bootstrap modal from a different webpage

If you're looking to open multiple modals with different content displayed from HTML files, check out this example below: <div id="how-rtm-works" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" ...

Enable search functionality for jQuery Select2 values that have been formatted by a formatter function

Trying to use a formatter with select2 for better alignment of code and description elements, but the plugin seems to be searching based only on the description rather than the entire text. This may be because it's only looking at the original <opt ...

creating an identical copy of a dynamic element's size

I am currently working on a project using react js where I need to incorporate multiple images. My goal is to have standard background divs / rectangles that match the exact size of each image, allowing for animations to be performed on top of them. The sn ...

Javascript error specific to Internet Explorer. Can't retrieve the value of the property 'childNodes'

After removing the header information from the XML file, the issue was resolved. Internet Explorer did not handle it well but Firefox and Chrome worked fine. An error occurred when trying to sort nodes in IE: SCRIPT5007: Unable to get value of the proper ...

What is the best way to execute operations on two distinct datasets within a single function using RxJS?

Is there a way to perform operations on two separate data collections within a single function in RxJS, returning an observable instead of void? This function is located within a service and I intend to subscribe to it from my component. I believe some re ...

Using a custom filter in AngularJS allows for seamless data filtering directly from the initial dataset

My goal is to implement a custom filter that will allow me to filter data based on a search word. The scope attribute gets populated in the controller's scope as shown below: naApp.controller('naCareNewTicketCtrl', ['$scope', &apo ...

Delivering a JSON response containing an item within an array

I am struggling to find the correct way to access the error message related to the 'firstname' field in the JSON-encoded object. The error message states that the length of the value for 'firstname' must be at least 3 characters long. ...

Having issues with jQuery's .text() method not functioning as expected on XML elements

Looking at the javascript code below: function getAdminMessageFromXML(xml) { alert('xml: ' + xml); alert("Text of admin message: " + $(xml).find('dataModelResponse').find('adminMessage').text()); return $(xml).fin ...

Modifying a JavaScript code with document.write(variable)

I am working with a Javascript function function setComparison(data) { var w= window.open('', 'comparison', 'width=600, height=400'); w.document.open(); w.document.write(getComparisonContent(data)); w.document ...

What is preventing Protractor from detecting Angular on a site that has been automatically initialized with Angular?

Whenever I try to utilize browser.get() in my code, I encounter the following error: Error: Angular could not be found on the page http://localhost:5000/#/login debug=timing&saveLogs=true&displayAll=true : angular never provided resumeBootstrap A ...