0

I was given this question by a prospective client to solve and I wasn't able to on time, only the makeSFns function can be altered and as I was altering to give specific square values to match the square function (based on position in arr) I kept getting the error of funcs[i] is not a function which is weird because the square function its being compared to is returning a number, how does something that's expecting a function match a number?

//Task: fix makeSFns function to show correct answer
var arr = [ Math.random(), Math.random(), Math.random(), Math.random() ];
var square = function (x) { return x * x; };

function makeSFns(arr, square) {
    var fns = [];
    for (var i = 0; i < arr.length; i++) {
        fns.push(function() {
            return square(arr[i]);
        });
    }
    return fns;
}

var funcs = makeSFns(arr, square);

isEqual = true;
for (var i = 0; i < arr.length; i++) {
    if (funcs[i]() !== square(arr[i])) {
        isEqual = false;
        console.log('wrong answer');
        break;
    }
}
if (isEqual) console.log('correct answer');

Some asking how I got the error, I tried finding a way to get position in arr and then returning

var position = 0; //outside the function

for (var i = 0; i < arr.length; i++) {
    return square(arr[i]);             //replacing the push function
    position + 1; 
 }
10
  • My first guess is that funcs ended up being empty, so funcs[i] was undefined, which is not a function. Commented Mar 12, 2018 at 22:07
  • 2
    I kept getting the error ... run your snippet ... no such error ... the code you posted in the question is obviously not the code that produces the error ... as an aside ... var i -> let i Commented Mar 12, 2018 at 22:12
  • 1
    Show us how you altered the code so that it threw funcs[i] is not a function. Commented Mar 12, 2018 at 22:13
  • @Olli is there any reason for passing function(){return square(x);} in push? Commented Mar 12, 2018 at 22:18
  • @JaromandaX, Bergi Updated, Yajiv that's how I got the question Commented Mar 12, 2018 at 22:22

4 Answers 4

1

you are passing arr[i] into square function inside makeSFns but this value lost as it is not a true closure.

//Task: fix makeSFns function to show correct answer
var arr = [ Math.random(), Math.random(), Math.random(), Math.random() ];
var square = function (x) { return x * x; };

function makeSFns(arr, square) {
  return arr.map((num, i)=>()=>{
    return square(arr[i])
  });
}

var funcs = makeSFns(arr, square);

isEqual = true;
for (var i = 0; i < arr.length; i++) {
    if (funcs[i]() !== square(arr[i])) {
        isEqual = false;
        console.log('wrong answer');
        break;
    }
}
if (isEqual) console.log('correct answer');

Sign up to request clarification or add additional context in comments.

8 Comments

it shows the inputs which are random numbers between 0 and 1, and then it shows the outputs, which are the squared version. 0.5*0.5 is 0.25 if you didn't know.
plus that's not the question, it doesn't matter it doesn't alert "correct answer"
but his question was why his function was not being called inside the second loop, and it was being called it was just that the value wasn't being passed to it. the comment is irrelevant, and he can easily put it in himself, since he wrote that code. unecessary
here you go, pedantic person
check the definition of pedantic
|
0

It is a classic, since the push function is called after the loop, it's referencing the last known i, it is not correctly captured.

//Task: fix makeSFns function to show correct answer
var arr = [ Math.random(), Math.random(), Math.random(), Math.random() ];
var square = function (x) { return x * x; };

function makeSFns(arr, square) {
    var fns = [];
    for (var i = 0; i < arr.length; i++) {
        (function(n) {
          fns.push(function() {
            return square(arr[n]);
          });
        })(i);
    }
    return fns;
}

var funcs = makeSFns(arr, square);

isEqual = true;
for (var i = 0; i < arr.length; i++) {
    if (funcs[i]() !== square(arr[i])) {
        isEqual = false;
        alert('wrong answer');
        break;
    }
}
if (isEqual) alert('correct answer');

More on the subject:

Edit: an interesting tranformation done by TypeScript when using the let keyword:

TS

for (let i = 0; i < arr.length; i++) {
    fns.push(function() {
        return square(arr[i]);
    });
}

JS

var _loop_1 = function (i) {
    fns.push(function () {
        return square(arr[i]);
    });
};
for (var i = 0; i < arr.length; i++) {
    _loop_1(i);
}

Comments

0

It is because the array's reference is not available to the function being pushed into fns array, a classic javascript scenario.

//Task: fix makeSFns function to show correct answer
//Task: fix makeSFns function to show correct answer
var arr = [ Math.random(), Math.random(), Math.random(), Math.random() ];
var square = function (x) { return x * x; };

function makeSFns(arr, square) {
    var fns = [];
    for (var i = 0; i < arr.length; i++) {
        let myFn = function(myInput) {
            return square(myInput); 
        };
        fns.push(myFn.bind(null,arr[i]));
    }
    return fns;
}

var funcs = makeSFns(arr, square);

isEqual = true;
for (var i = 0; i < arr.length; i++) {
    if (funcs[i]() !== square(arr[i])) {
        isEqual = false;
        console.log('wrong answer');
        break;
    }
}
if (isEqual) console.log('correct answer');

Comments

0

There's a solution to this that requires changing one keyword only:

  function makeSFns(arr, square) {
    var fns = [];
-    for (var i = 0; i < arr.length; i++) {
+    for (let i = 0; i < arr.length; i++) {
       fns.push(function() {
         return square(arr[i]);
       });
     }
    return fns;
  }

Using let changes the scope of i and makes it behave like a separate closure. Each iteration in the for loop will have it's own instance of i.

Comments

Your Answer

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.