0

I know my code below is wrong but there is clearly some bit of information I am missing. I have to write much more complex higher order functions but if I do not truly understand simple ones I have no chance.

hof.add should return the total of the two arguments passed. Very simple... But given I am to create this higher order function is must use closure.


    hof.add = function(add) {
      function makeAdd(a, b) {
        return add(a + b);
      }
      return makeAdd;
    };

it('returns total of the two arguments', () => {
        expect(hof.add(56, 5)).to.be.equal(56 + 5);
        expect(hof.add(91, -71)).to.be.equal(91 + -71);
      });

(framework given to build on top of)

hof.add = function() { };
SirNail
  • 85
  • 1
  • 8
  • 6
    I'm not quite sure what you're asking. Do you want an explanation of this code, or to alter it to achieve some specific task? If so, what are you trying to achieve? – Robin Zigmond Sep 05 '19 at 21:24
  • 3
    What is the most confusing is that there are three functions in the code, all named `add`: `hof.add`, `add`, and `addFunc`. Maybe it's easier if you renamed the `hof.add` to `makeAdder`, and the `add` parameter to just `callback`. – Bergi Sep 05 '19 at 21:25
  • 2
    I would think that `return add(a + b);` would be `return add(a, b);` where add would be some method that combines them. – epascarello Sep 05 '19 at 21:26
  • 2
    "*The function add should return the total of the two arguments passed*" - which of the `add` functions? Please post how you were trying to call the function(s). – Bergi Sep 05 '19 at 21:28
  • 1
    Possible duplicate of [How do JavaScript closures work?](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – EugenSunic Sep 05 '19 at 21:30
  • specifically asking about closures. not a general question on how to create a function. – SirNail Sep 05 '19 at 21:35
  • @Tony there are many previous questions on SO about closures. If you have something more specific to ask about them then please edit your original question to make it clearer. I would be happy to help you but I still have no idea what the question is, and therefore how to help. – Robin Zigmond Sep 05 '19 at 22:06
  • @Tony it's totally unclear 1: How you want to use that function (factory, whatever). 2: what boggles you exactly with the code you wrote and what you expect the output to be. Just show a line of code where you actually *use* that function. You're mentioning in your question *`"of the two arguments passed"`* but your function accepts only **one** - the `add` argument. – Roko C. Buljan Sep 05 '19 at 22:11
  • @RobinZigmond I have just updated it. Thanks for your help! I have to write higher order functions and therefore cannot simply write an add function outside of original function. It must use closure to add two arguments together. Hope this helps. – SirNail Sep 05 '19 at 22:12
  • @RokoC.Buljan added the testing I wrote if that makes this any clearer. But not sure what else I can say. Have updated the question now. Thank you for the help – SirNail Sep 05 '19 at 22:14
  • The tests are helpful, thanks. So, you waht to use `hof.add(56, 5)` passing two arguments, but take a closer look: `function(add)` << how many are expected? – Roko C. Buljan Sep 05 '19 at 22:15
  • @Tony thanks for the edit, but if those tests are an accurate guide to what you want `hof.add` to do then just `hof.add = ((a, b) => a + b);` is the obvious way to do it, which doesn't involve higher order functions or closures at all. So I'm still confused as to what you are asking. – Robin Zigmond Sep 05 '19 at 22:16
  • Thanks. Well yes there are certainly easier ways to do it but I was given this framework today (added below the testing) which I can't delete only add to. And @RokoC.Buljan I suppose it would be more logical for it to return an actual function there instead of just add...? – SirNail Sep 05 '19 at 22:19

3 Answers3

0

Why do you create a function inside the returned function instead of just creating the right function initially? I would go something like this:

hof.add = function(a, b) {
    return (a + b);
};
jacob13smith
  • 919
  • 5
  • 12
0

Higher order functions (HOF) is just a fancy name for a function that accept a function as an argument or returns another function. If I understand you better, you are trying to create an adder function that can be used to add numbers. Using your example hof.add is an HOF that receives a function, and returns another function that can be used for adding two numbers together

 hof.add = function(add) {
  function addFunc(a, b) {
    return add(a, b);
  }
  return addFunc;
}

function add(a, b){
  return a + b
}

const addNumbers = hof.add(add);
addNumbers(3, 14)
//17 as answer
addNumbers can recieve any two numbers and it will add them together.

add is a function that adds two numbers together which is received as a parameter in hof.add. hof.add functions returns a function called addFunc who in turn receives two arguments to add together. Cheers

James Oshomah
  • 224
  • 2
  • 12
  • yes this is basically my question thank you. But, I am struggling with closure and the ```jsfunction add(a, b){ return a + b } thow could you write this inside of the original function keeping its functionality and still passing it the arguments? – SirNail Sep 05 '19 at 22:02
0

If you want to use only one argument-name, perhaps you meant to destructure it: function(...add)

const not_hof = {};

// Cheating by using destructuring (...add) 
// and not a HOF since accepts only Numbers as arguments 
not_hof.add = function(...add) {  
  const makeAdd = add.reduce((prev, curr) => {
    return prev + curr;
  }, 0);
  return makeAdd; // and still not a HOF since it returns a Number 
};

console.log(not_hof.add(2, 3));              // 5
console.log(not_hof.add(9, 1, 10));          // 20
console.log(not_hof.add(1, 1, 1, 1, 1, 1));  // 6

PS: The above function can be also expressed like:

not_hof.add = (...add) => add.reduce((prev, curr) =>  prev + curr, 0);

Not a HOF (higher order function)

Although many would say the above is a higher order function - since it returns Array.prototype.reduce, it's actually not:

Wikipedia - Higher order function

In mathematics and computer science, a higher-order function is a function that does at least one of the following:

  • takes one or more functions as arguments (i.e. procedural parameters),
  • returns a function as its result.

But add is not a procedural function argument; i.e:

procedure P(f):
return f(2,3) * f(9,1)

and it does not return a function; rather a Number returned by Array.prototype.reduce.

1. HOF - One or more functions as arguments

To at least pass a function as argument:

const helper = { // Helper functions
  add(a, b) { return  Number(a) + Number(b); },
};


const hof = {};
hof.add = function(fn, add1, add2) { // HOF since it takes a function as argument
  return fn(add1, add2);             // (Returns a Number)
};

// ...But it takes three arguments
console.log(hof.add(helper.add, 56, 5)); // 61

2. HOF - Return a function

To at least return a function:

const hof = {};

hof.add = function(add) { // (Takes a Number argument)
  function makeAdd(b) {
    return add + b;
  }
  return makeAdd;         // HOF since it returns a function
};

// But accepts a single argument at each call
console.log(hof.add(56)(5)); // 61

or like

const hof = {};
hof.add = function(add1, add2) { // NOT LIKE YOUR EXAMPLE, 2 arguments are expected!
  function makeAdd() {
    return add1 + add2;
  }
  return makeAdd; // HOF since it returns a function
};

// ...The function had to be executed ()
console.log(hof.add(56, 5)());     // 61

but in such case it fails what your test states:

it('returns total of the two arguments', () => { // nope :( only one argument here...

HOF with closure

Allows to invoke the function multiple times with a Function.prototype.toString() in order to return at the last call the string

const hof = {};

hof.add = function(add) {
  let sum = add;    // Store in local scope
  const makeAdd = (b) => {
    sum += b;       // Access to lexical environment variables
    return makeAdd; // Returns a function (self)  
  }
  makeAdd.toString = () => sum;
  return makeAdd;   // HOF since we return a function
}

const result = hof.add(1)(2)(2)(56);
console.log(result)         // (f) 61
console.log(typeof result); // function
console.log(result == 61)   // true
console.log(result === 61)  // false
// A legitimate test might break since the strict equality operator fails.

Let's keep it simple. No closure, no HOF

If the first example using Array destructuring and Array.prototype.reduce() is not needed, than just stick to the simplest form of a function declaration:

const not_hof = {
  add: (a, b) => a + b,
  sub: (a, b) => a - b,
  // etc...
};

console.log(  not_hof.add(56, 5)  ); // 61
Community
  • 1
  • 1
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313