lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


 > I would move the metatable construction outside memoize because it
 > never changes.

I understand the impulse, but since I'm already allocating a table at
every call, I don't mind allocating a second table at every call.

 > You could also [use the __index metamethod instead of testing for nil]

I like this idea; I hope my colleague will like it as well.  It makes
the code a little cleaner and the 'fast path' (a hit in the cache)
will be a little faster.   But notice it's even nicer if you just
capture the function lexically:

  function memoize (f)
    local function index(t, k)
      local function update(v, ...)
        assert(select('#', ...) == 0)
        t[k] = v
        return v
      end
      return update(f(k))
    end
    local cache = setmetatable({ }, { __mode = 'k', __index = index })
    return function (x, ...)
             assert(select('#', ...) == 0)
             return cache[x]
           end
  end

And if you're willing to lose should f return multiple results, as in
your example code, it becomes even simpler:

  function memoize (f)
    local function index(t, k)
      t[k] = f(k)
      return t[k]
    end
    local cache = setmetatable({ }, { __mode = 'k', __index = index })
    return function (x, ...)
             assert(select('#', ...) == 0)
             return cache[x]
           end
  end

I myself would rather have the extra protection, since it occurs only
on the slow path anyway.


Norman