Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trampolining operation() #57

Open
mdda opened this issue Jun 9, 2014 · 4 comments
Open

Trampolining operation() #57

mdda opened this issue Jun 9, 2014 · 4 comments

Comments

@mdda
Copy link

mdda commented Jun 9, 2014

In the given solution, the first time that

function repeat(operation, num) {
}

is called, no operation() is performed, since the actual operation() call is returned in the continuation being passed back. This seems puzzling.

Wouldn't it make more sense to perform an operation() for each call to repeat(), and just pass back the next step in the continuation? (i.e. move the operation() call up two lines?)

If, OTOH, I fail at understanding how this should be done, please be gentle :-)

@timoxley
Copy link
Owner

timoxley commented Jun 9, 2014

Good point, though it doesn't really matter that much, there are multiple possible solutions:

As you suggested:

function repeat(operation, num) {
  if (num <= 0) return
  operation()
  return function() {
    return repeat(operation, --num)
  }
}

I think I prefer this though:

function repeat(operation, num) {
  return function() {
    if (num <= 0) return
    operation()
    return repeat(operation, --num)
  }
}

and the current solution looks like:

function repeat(operation, num) {
  if (num <= 0) return
  return function() {
    operation()
    return repeat(operation, --num)
  }
}

@AndyHoang
Copy link

Could you please explain the repeat function?
As the exercise before it (https://github.com/timoxley/functional-javascript-workshop/tree/master/problems/blocking_event_loop)
As for as I know, repeat seem like to call an action several times. So in this ex, we return a function, and inside of this function, we call operation() one time, then try to call a repeat num-1 times again.
So how exactly operation was called?
Normally I try to write some test case for testing, but I dont know how to write for this one, as a result I don't understand at all :(
The blocking event loop ex, I barely understand it. Maybe it's the reason I couldn't get this one. Could you point me some more tut or exercise about this blocking event loop? (I read this one #62)
I lost here :(

@robinpokorny
Copy link

I do not like the return repeat(operation, --num) line. To be precise I do not like the return keyword. It is not needed and it is not present in current official solution. Shouldn't it be removed?

@nsubordin81
Copy link

I'm was confused about this one. I wasn't able to figure out the trampoline solution without looking up some context about why we use it in javascript. The way I understand it now, one of the main reasons is to make up for lack of tail-call optimization in javascript. For this problem, that would mean even though repeat's last call is the recursive one, the interpreter will still spin up a new stack frame for each recursive invocation.

Going off of other sources where I was reading about this, I arrived at a solution that uses bind() to ensure that the recursive call execution is deferred until trampoline invokes it within the loop. However, the official solution did not seem to need this to prevent the stack overflow and I am not sure why.

I think I get the main point that each step of the recursion should be executing rather than setting up a bunch of placeholders until we get to the base case, but with the resources and instructions provided, I was not as clear on why the stack overflow would be happening and how this solution prevents it

Here was my solution which worked but seems to have unnecessary elements to it:

function repeat(operation, num) {
  // Modify this so it doesn't cause a stack overflow!
  if (num <= 0) return
  operation()
  return repeat.bind(null, operation, --num)
}

function trampoline(fn) {
  while(fn && fn instanceof Function) {
    fn = fn()
  }
  return fn
  // You probably want to implement a trampoline!
}

module.exports = function(operation, num) {
  // You probably want to call your trampoline here!
  return trampoline(repeat.bind(null, operation, num))
}

and for contrast the official solution:

function repeat(operation, num) {
      return function() {
        if (num <= 0) return
        operation()
        return repeat(operation, --num)
      }
    }

    function trampoline(fn) {
      while(fn && typeof fn === 'function') {
        fn = fn()
      }
    }

    module.exports = function(operation, num) {
      trampoline(function() {
        return repeat(operation, num)
      })
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants