[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Soliciting criticism of memoize function
- From: Norman Ramsey <nr@...>
- Date: Thu, 15 May 2008 20:38:24 -0400
> 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