3

I've started learning JS recently, and this is my first dive into functional language territory.

Was doing the "trampoline" exercise in the functional-javascript-workshop npm module, and came across an interesting difference between my own solution and the official solution. Both work perfectly fine, but I'm at a loss as to what exactly is the practical difference between them. I understand my own solution pretty well, but don't exactly understand why the other one works too.

My Solution

function repeat(op, num) {
  var _repeat = function() {
    if (num <= 0) return;
    op();
    return repeat(op, --num);
  };

  return _repeat;
}

function trampoline(f) {
  while (f instanceof Function) {
    f = f();
  }
  return f;
}

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

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)
  })
}

Specifically, I'm curious about the last part - why does the official solution create an annonymous function instead of just passing repeat?

Joel Gallant
  • 315
  • 4
  • 21
  • I don't think there's any difference in code, only thing that I notice is that in official solution you can know right away that trampoline is called with a function, where in your solution, one has to check what are you returning. And on a side note, be careful with this official solutions, avoiding semicolons in javascript might turn out ugly if you don't know this works "under the hood". – Marko Gresak Nov 18 '14 at 00:43
  • Hey Joel -- I have a question for you. I was hung up on this exercise. I can't see when or if ever "fn && typeof fn === "function" would ever not be true. slightly confused. – james emanon Mar 03 '15 at 22:19

2 Answers2

1

Take a look at the trampoline:

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

Notice how it keeps iterating as long asfn is a function, which it invokes.

So theoretically you can have as many nested functions and get the same result:

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

Demo: http://jsbin.com/yixaliyoye/1/edit

The Official solution has one more redundant step than your solution. No real reason for it, other than the original author probably thought it looked more readable.

Miguel Mota
  • 20,135
  • 5
  • 45
  • 64
1

There's not really a reason.

Except maybe that the trampoline will make the all calls, while in your version the first invocation of repeat is done outside of it. This might be considered cleaner, and could make an actual difference when trampoline was more sophisticated (e.g. wrapping all execution in a try-catch).

Bergi
  • 630,263
  • 148
  • 957
  • 1,375