1

spending more and more time studying JS and I'm loving it. However, as I begin to deal with slightly more complex functions (IIFE, anonymous, etc) - I'm beginning to struggle and would love some pointers. Would appreciate all the help and advice in explaining why my line of code (Line 15) is causing so much grief!

The assignment instructions are below:

  1. Build a function and assign it to a variable named applyAndEmpty.
  2. The function should take in an input number and a queue of functions as parameters.
  3. Using a for loop, call the functions in the queue in order with the input number, where the results of each function become the next function’s input. Additionally, the queue should be empty after the function is called.
  4. Lastly, call the applyAndEmpty function using the provided start variable and the puzzlers Queue as arguments, and alert the result.

So far, I know I have correctly setup the for loop and am on the right track as far as calling the actual function, but I simply can't figure out the final line within the loop. I realize I need to use the array shift method in order to sequentially begin emptying out the array, however, I am not sure how I can apply the input parameter to each function, store that as input and then continue to cycle through as I remove the functions, before returning a result.

// The following array and 'start' variable are given (by the assignment):

var puzzlers = [
  function(a) { return 8 * a - 10; },
  function(a) { return (a - 3) * (a - 3) * (a - 3); },
  function(a) { return a * a + 4; },
  function(a) { return a % 5; }
];
var start = 2;

// My code begins below:

var applyAndEmpty = function(input,queue) {
  for(var i = 0; i < queue.length; i++) {
    input = queue[i].shift(); // This is my problem area - I simply don't understand!
     }
  return input;
};

alert(applyAndEmpty(start,puzzlers));

5 Answers 5

2

By this syntax you are calling shift on the item in the array, not the array. So instead of this:

input = queue[i].shift()

Try this:

var func = queue.shift()  //get the function from the array
input = func(input) //call the function, I'd recommend you don't overwrite your param, rather store to another var (helpful in debugging)

Since this is an assignment, I won't fix the rest (teach a man to fish...), but as a hint, you should be storing your previous answer so that you can apply it as an argument for the current function.

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

3 Comments

Jusopi, thanks for your reply - I'm sure you meant queue.shift( ), my intention with writing out "input = ...." is to assign the result of the current function as the new "input" parameter.
oh good catch, fixed. You could write the output to your input param however in debugging you may want to know the original input, ergo why I mentioned having an additional var like crnt or something. Also I wanted to keep what I answered to be as high level as I could since this is an assignment.
Ah yeah, I meant an assignment (exercise) - I am working on on Codeschool's site. I already have the answer but I'm trying to understand why.
2

You need to actuall run the function with the input you collected:

input = queue[i](input)

and you don't want to use .shift - that's a different way to consume an array in a loop (it removes the "bottom" item in the array - but it changes the original array, which may have side effects elsewhere). That has its uses, but it conflicts with the for loop, which is what you were asked to use.

EDIT Breakdown:

queue[i]        -> the current function
queue[i](       -> it's a function, so run it...
queue[i](input) ->...with the previous output as input

EDIT carrying on discusssion in comments

It is rather odd having both .shift AND a for loop (which the requirement for "having an empty queue at the end" seems to imply). Usually you use shift with a while

var input = initial_value;
var current_function;
while (current_function = queue.shift()) {
  input = current_function(input);
}

I guess you can mimic the while loop with a for loop

var current_function;
for (var input = INITIAL_VALUE; current_function = queue.shift(); ) {
  ....

But it doesn't make sense. You can simply empty the array at the end...

3 Comments

I understand it could have bad side effects, especially when used in conjunction with a for loop - but the assignment had asked for it :( How would you tackle it if .shift wasn't required?
Is shift required? That is a way to empty out the queue, but it isn't in the assignment. The for loop requirement seems to be at odds with the shift() actually. You will see a subtle bug when you realize not all of your functions get run...
I agree with @MichaelM, having both .shift AND a for loop is odd
1

shift is an array method, and removes and returns the first element of the array. In the case of your function, the array is queue which in an array of functions. You should use input = queue.shift(); and not input = queue[i].shift(); After you do this, input will be a function, but you need to run the function with the correct parameter. Rather than post a solution to your question, I hope this information will get you started in the right direction.

super fancy solution:

var applyAndEmpty = function(input,queue) {
  return queue.reduce(function(prev,cur) { return cur.call(this,prev);}, input);
};

3 Comments

Brian, thanks for your reply - I did not remember that shift not only removes the first element of an array, but also returns it...
Edited my answer with a solution that I would have used for this.
reduce almost always is the most elegant approach - but for it does not actively mutate the array it is operating on, this approach misses the following part of the OP's challenge ... >>Additionally, the queue should be empty after the function is called.<<
1

Using a for loop, ... Additionally, the queue should be empty after the function is called.

for loop based variant ...

var puzzlers = [
  function(a) { return 8 * a - 10; },
  function(a) { return (a - 3) * (a - 3) * (a - 3); },
  function(a) { return a * a + 4; },
  function(a) { return a % 5; }
];
var startValue = 2;


var applyAndEmpty_for = function (value, queue) {
  for (var fct, idx= 0, len = queue.length; idx < len; idx++) {

    fct = queue[idx];

    value = fct(value);
  }
  queue.length = 0; // empty queue explicitly.

  return value;
};


console.log(applyAndEmpty_for(startValue, puzzlers), puzzlers); // 3 []

while loop based variant ...

var puzzlers = [
  function(a) { return 8 * a - 10; },
  function(a) { return (a - 3) * (a - 3) * (a - 3); },
  function(a) { return a * a + 4; },
  function(a) { return a % 5; }
];
var startValue = 2;


var applyAndEmpty_while = function (value, queue) {
  var fct;
  while (fct = queue.shift()) { // empty queue by shifting.

    value = fct(value);
  }
  return value;
};


console.log(applyAndEmpty_while(startValue, puzzlers), puzzlers); // 3 []

Comments

0

This is a CodeSchool JavaScript RoadTrip Part-3 (Level 1, Challenge 13) right?

This I found the most toughest challenge in this course so far. But I figured out the simplest solution after spending hours scratching my head.

var puzzlers = [
  function(a) { return 8 * a - 10; },
  function(a) { return (a - 3) * (a - 3) * (a - 3); },
  function(a) { return a * a + 4; },
  function(a) { return a % 5; }
];

var start = 2;

var applyAndEmpty = function(input, queue) {
  var length = queue.length;
  for(var i = 0; i < length; i++) {
    input = queue.shift()(input);
  }
  return input;
};

alert(applyAndEmpty(start, puzzlers));

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.