1

I was asked to create a function to achieve the following, add up some number and then call the value of them all, ie a chained function of sorts, I created a bad solution, but cannot think of a better way of doing this.

add(5).add(10).add(20).value();

The interview question just started with an empty function

function add() {
}

My solution is below, does anybody have any other suggests as I am interested, I've looked at currying, binding etc but not come up with an elegant solution.

var slice = Array.prototype.slice
function add() {
 var arr = slice.call(arguments);
 return {
 add: function() {
 arr = arr.concat(slice.call(arguments)) 
 return this;
 },
 value: function() {
 return arr.reduce(function(prev, curr) {
 return prev + curr;
 });
 }
 }
};

Edit Just to clarify I was wondering if there is a way to do this without returning an add function but to call the existing add function. I think the way that it has been done below is nice, but I think the interviewer was looking for something non-simple.

asked Apr 11, 2016 at 17:36
6
  • 1
    I don't find the requirements particularly clear. Commented Apr 11, 2016 at 17:38
  • 2
    Your solution looks fine. I don't see the recursion just chaining. Commented Apr 11, 2016 at 17:39
  • Can you clarify the requirements of what you need to achieve here? At the moment, a recursive function doesn't seem best suited to your purpose. Commented Apr 11, 2016 at 17:39
  • Never mind, I understand the requirements now; my bad. Commented Apr 11, 2016 at 17:45
  • I don't like it's mutable. For example a = add(5).add(6); b=a.add(7) and we have a.value()==b.value() Commented Apr 11, 2016 at 17:47

3 Answers 3

6

Why so complicated? Don't carry that array of values around with you. Also, try to stay functional and don't mutate it.

function add(x) {
 return {
 value: function() {
 return x;
 },
 add: function(y) {
 return add(x+y);
 }
 };
}

The key insight here seems to be that chaining doesn't just mean to return this, but rather any object of the same class. Immutability dictates that it should be a different object when it has a different sum attached to it.

answered Apr 11, 2016 at 18:17
Sign up to request clarification or add additional context in comments.

2 Comments

Thats a nice solution, pity I did not think of it
@itzmukeshy7: Should be pretty self-explanatory, and works with the examples given in the OP. What parts don't you understand?
0

seems overcomplicated tbh, here's my answer but maybe I'm not understanding part of the requirements

function add(x) {
 return {
 val: 0,
 add: function(x) {
 this.val += x;
 return this;
 },
 value: function() {
 return this.val;
 }
 }
};
answered Apr 11, 2016 at 18:15

2 Comments

Your first call (to the add function, not to the method) doesn't seem to take an argument. And why use arguments[0] instead of just declaring a parameter?
yeh it's using the format from the original answer, I'll update it to make more sense
0

I like with your idea of lazy calculation, that's why we should keep the chain of operations. But implementation using array has drawback of mutability (see my comment)

I have just written somewhat close to how I see the solution

var Calculator = function(initialValue){
 function createOperator(operation) {
 return function(value) {
 return createInstance(operation.bind(null, value));
 }
 }
 function createInstance(reduce) {
 return Object.freeze({
 'add': createOperator((val) => reduce() + val),
 'subtract': createOperator((val) => reduce() - val),
 'multiply': createOperator((val) => reduce() * val),
 'divide': createOperator((val) => reduce() / val),
 'value': reduce
 });
 }
 return createInstance(()=>initialValue);
}
Calculator(0).add(5).multiply(4).subtract(12).divide(2).value(); //returns 4 

In your problem lazy calculation in not really required, but if we want to preserve chain of operations for multiple use, here it goes. See this example

var Calculation = function(){
 function createOperator(operation) {
 return function(value) {
 return createInstance(operation.bind(null, value));
 }
 }
 function createInstance(apply) {
 return Object.freeze({
 'add': createOperator((val, initial) => apply(initial) + val),
 'subtract': createOperator((val, initial) => apply(initial) - val),
 'multiply': createOperator((val, initial) => apply(initial) * val),
 'divide': createOperator((val, initial) => apply(initial) / val),
 'apply': apply
 });
 }
 return createInstance((initialValue)=>initialValue);
}();
var calc = Calculation.add(5).multiply(2).subtract(11);
calc.apply(2); //returns 3
calc.apply(10); //returns 19
answered Apr 12, 2016 at 11:42

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.