How do I write a generic memoize function?

后端 未结 15 1627
情话喂你
情话喂你 2020-12-09 05:25

I\'m writing a function to find triangle numbers and the natural way to write it is recursively:

function triangle (x)
   if x == 0 then return 0 end
   retu         


        
相关标签:
15条回答
  • 2020-12-09 06:02

    You're also asking the wrong question for your original problem ;)

    This is a better way for that case:

    triangle(n) = n * (n - 1) / 2

    Furthermore, supposing the formula didn't have such a neat solution, memoisation would still be a poor approach here. You'd be better off just writing a simple loop in this case. See this answer for a fuller discussion.

    0 讨论(0)
  • 2020-12-09 06:03

    I bet something like this should work with variable argument lists in Lua:

    local function varg_tostring(...)
        local s = select(1, ...)
        for n = 2, select('#', ...) do
            s = s..","..select(n,...)
        end
        return s
    end
    
    local function memoize(f)
        local cache = {}
        return function (...)
            local al = varg_tostring(...)
            if cache[al] then
                return cache[al]
            else
                local y = f(...)
                cache[al] = y
                return y
            end
        end
    end
    

    You could probably also do something clever with a metatables with __tostring so that the argument list could just be converted with a tostring(). Oh the possibilities.

    0 讨论(0)
  • 2020-12-09 06:04

    Please don't recurse this. Either use the x*(x+1)/2 formula or simply iterate the values and memoize as you go.

    int[] memo = new int[n+1];
    int sum = 0;
    for(int i = 0; i <= n; ++i)
    {
      sum+=i;
      memo[i] = sum;
    }
    return memo[n];
    
    0 讨论(0)
  • 2020-12-09 06:06

    Here's something that works without converting the arguments to strings. The only caveat is that it can't handle a nil argument. But the accepted solution can't distinguish the value nil from the string "nil", so that's probably OK.

    local function m(f)
      local t = { }
      local function mf(x, ...) -- memoized f
        assert(x ~= nil, 'nil passed to memoized function')
        if select('#', ...) > 0 then
          t[x] = t[x] or m(function(...) return f(x, ...) end)
          return t[x](...)
        else
          t[x] = t[x] or f(x)
          assert(t[x] ~= nil, 'memoized function returns nil')
          return t[x]
        end
      end
      return mf
    end
    
    0 讨论(0)
  • 2020-12-09 06:08

    I've been inspired by this question to implement (yet another) flexible memoize function in Lua.

    https://github.com/kikito/memoize.lua

    Main advantages:

    • Accepts a variable number of arguments
    • Doesn't use tostring; instead, it organizes the cache in a tree structure, using the parameters to traverse it.
    • Works just fine with functions that return multiple values.

    Pasting the code here as reference:

    local globalCache = {}
    
    local function getFromCache(cache, args)
      local node = cache
      for i=1, #args do
        if not node.children then return {} end
        node = node.children[args[i]]
        if not node then return {} end
      end
      return node.results
    end
    
    local function insertInCache(cache, args, results)
      local arg
      local node = cache
      for i=1, #args do
        arg = args[i]
        node.children = node.children or {}
        node.children[arg] = node.children[arg] or {}
        node = node.children[arg]
      end
      node.results = results
    end
    
    
    -- public function
    
    local function memoize(f)
      globalCache[f] = { results = {} }
      return function (...)
        local results = getFromCache( globalCache[f], {...} )
    
        if #results == 0 then
          results = { f(...) }
          insertInCache(globalCache[f], {...}, results)
        end
    
        return unpack(results)
      end
    end
    
    return memoize
    
    0 讨论(0)
  • 2020-12-09 06:08

    In Perl generic memoization is easy to get. The Memoize module is part of the perl core and is highly reliable, flexible, and easy-to-use.

    The example from it's manpage:

    # This is the documentation for Memoize 1.01
    use Memoize;
    memoize('slow_function');
    slow_function(arguments);    # Is faster than it was before
    

    You can add, remove, and customize memoization of functions at run time! You can provide callbacks for custom memento computation.

    Memoize.pm even has facilities for making the memento cache persistent, so it does not need to be re-filled on each invocation of your program!

    Here's the documentation: http://perldoc.perl.org/5.8.8/Memoize.html

    0 讨论(0)
提交回复
热议问题