1

I have a class that has two functions. Add, which adds a function to an array, and Execute which executes the array of function against its argument. My code is:

class LazyEvaluation {
  constructor(){
    this.functionQueue = []
  }

  add(fn){
    this.functionQueue.push(fn)
    return this
  }

  evaluate(target){
    for (let i = 0; i < this.functionQueue.length; i++){
      let newArray = target.map(this.functionQueue[i])
      return newArray
    }
  }
}

As it stands, this code works when i only have one function in the array. My problem is as soon as there is more than one function in the array the execute function creates a new array for each function.

For example, when the functionQueue array has the following two functions:

(function timesTwo(a){ return a * 2 })
(function addOne(a) { return a + 1 })

And the execute function is given [1, 2, 3]

The output I need is [3, 5, 7] however I am getting two separate outputs of [2, 4, 6] and [2, 3, 4]

How do I ensure that the execute function doesn't create a new array for each function in the functionQueue?

2 Answers 2

2

You're returning too early in your for loop. You actually have to reduce your functions passing along the values from target:

class LazyEvaluation {
  constructor(){
    this.functionQueue = []
  }

  add(fn){
    this.functionQueue.push(fn)
    return this
  }

  evaluate(target){
    return target.map(x => 
      this.functionQueue.reduce((y, f) => f(y), x)
    );
  }
}

const sums = new LazyEvaluation();
sums.add(x => x * 2);
sums.add(x => x + 1);

console.log(
  sums.evaluate([1,2,3])
);

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

7 Comments

That won't produce the desired output.
@T.J.Crowder Ah, read a bit too fast there and jumped on the first "mistake" I saw in the code. Fixed it now! Thanks for the heads up
That's still not the output the OP said they want.
Because I chose different example data... It's not about reproducing the exact example outcome, it's about figuring out the logic, right? I expect the OP to read my code snippet and see it meets the requirement, not to only check the outcome of the console.log. Do you agree that's a valid approach?
Thanks, this worked! - just for the sake of understanding, would it be possible to explain why this worked? So, the results from the map of target is passed in to the reduce?
|
1

For example, when the functionQueue array has the following two functions:

(function timesTwo(a){ return a * 2 })
(function addOne(a) { return a + 1 })

And the execute function is given [1, 2, 3]

The output I need is [3, 5, 7] however I am getting two separate outputs of [2, 4, 6] and [2, 3, 4]

You need to feed the result of the first function into the second, etc.:

evaluate(target){
  return target.map(value => {
      for (const f of this.functionQueue) {
          value = f(value);
      }
      return value;
  });
}

Live Example:

class LazyEvaluation {
  constructor(){
    this.functionQueue = []
  }

  add(fn){
    this.functionQueue.push(fn)
    return this
  }

  evaluate(target){
    return target.map(value => {
        for (const f of this.functionQueue) {
            value = f(value);
        }
        return value;
    });
  }
}

const l = new LazyEvaluation();
l.add(function timesTwo(a){ return a * 2 });
l.add(function addOne(a) { return a + 1 });
console.log(l.evaluate([1, 2, 3]));

5 Comments

Is const f of this.functionQueue valid? const shouldn't be a variable that never going to be assigned again?
@Michael - Yes, it's valid -- did you notice the runnable example? :-) The semantics of const and let "variables" declared in loops are different from the behavior of var variables in loops: A different variable/constant is created for each loop iteration. for-of and for-in never try to modify the value of that variable, so you can use a constant. for does modify it, so you have to use let in that case (even though, again, it's a different variable each time).
@Michael - The new behavior is hugely useful in addressing the common closures in loops problem.
I noticed the runnable example, and even run it in my chrome console to be sure :) I know about let f of this.functionQueue but const j... sounds illogical for me.
@Michael - :-) It's logical if you dig deep enough, it's really a different variable/constant each time. for-of is syntactic sugar for acquiring an iterator, calling its next method to get a result object, and then assigning a variable/constant to the result's value property; then repeating the next call the next time. Here's a long-winded example: jsfiddle.net/x098rj7L

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.