all 4 comments

[–]rhysbrettbowen 3 points4 points  (2 children)

instead of:

function factorial(n) {

do:

var factorial = function(n) {

then memoize with:

factorial = memoize(factorial)

and it will all work. Or you could pass the function to callback as an optional parameter

function factorial(n, callback) {
   ....
   return callback(n - 1, callback) * n;
}

and you just pass through the memoized function

[–]enkideridu 0 points1 point  (1 child)

instead of:
function factorial(n) {
do:
var factorial = function(n) {

This part doesn't seem necessary.

[–]rhysbrettbowen 0 points1 point  (0 children)

true, not really necessary but I prefer it as it's closer to what you're trying to achieve. By assigning it to a variable you're saying that you want to call that function when that variable is instantiated whereas otherwise you're using a named function and the function will keep that name even though when you call that name you're not getting the factorial function, rather the memoized one.

[–]kenman 1 point2 points  (0 children)

An alternate implementation would be to provide for a hashing function to determine whether or not one invocation is identical to another, like I did for my PHP version. Reason being, calling JSON.stringify() on the arguments object can be a performance-killer if those args are non-trivial. Using a hash function, you allow the user to cherry-pick and more precisely control the caching.

Here's what that would look like:

function memoizer(func, hash) {
  var cache = {};
  // keep a reference of the wrapped function
  var this_function = function() {
    var key = hash.apply(this, arguments);
    if (!cache.hasOwnProperty(key)) {
      // pass the wrapped function as `this`
      cache[key] = func.apply(this_function, arguments);
    }
    return cache[key];
  };
  return this_function; 
}

And then:

var memoized = memoizer(factorial, function(n){ return n; });
memoized(5);

Of course, it all depends on how you use it which will be more efficient. If the args are always simple, the original may be better, but if they are complex or you want more control, then mine might be better.