Lua中缓存字符串之间分离函数调用中的昂贵表计算

我有许多操作字符串以提取有趣属性的函数。其中一个被许多函数调用的特殊函数非常昂贵,最终生成值表:

local function expensive(s)
  local t = nil
  return function()
    if not t then
      t = {}
      -- 与s一起进行了一些昂贵的操作,将项目添加到t中
    end
    return t
  end
end

local function fn1(s)
  local t = expensive(s)
  -- 使用t和s的其他快速操作
end

local function fn2(s)
  local t = expensive(s)
  -- 使用t和s的其他快速操作
end

local s1,s2 = 'a''b' 
fn1(s1) - 应为s1创建't'表
fn1(s2) - 应为s2创建't'表
fn2(s1) - 不应再为s1创建't'表
fn1(s2) - 也不应再为s2创建't'

如何使昂贵函数对于每个字符串仅创建一个表,在任何情况下都返回表?我宁愿不将表暴露给全局环境。我认为这可能可以通过巧妙使用闭包来实现,但我不太了解该构造。

点赞
用户1847592
用户1847592
本地缓存 = {}

本地函数 `expensive(s)`
  本地变量 `t` = 缓存[s]
  如果 `t` 为空,则执行以下操作:
    本地变量 `t` = {}
    -- 一些以 `s` 为参数的昂贵操作,同时将其结果添加至 `t`
    缓存[s] = `t`
  结束
  返回 `t`
结束
2017-05-18 16:44:10
用户5287638
用户5287638

Egor的答案可以完成这项工作,但是cache表可以被整个文件访问。为了隐藏它,您有一些选项。第一个是一个简单的do/end块。

local expensive
do
    local cache = {}
    expensive = function (s)
      local t = cache[s]
      if not t then
        t = {}
        -- 对s执行一些昂贵的操作,并将项目添加到t中
        cache[s] = t
      end
      return t
    end
end

另一个选项是自执行函数。

local expensive = (function ()
    local cache = {}
    return function (s)
      local t = cache[s]
      if not t then
        t = {}
        -- 对s执行一些昂贵的操作,并将项目添加到t中
        cache[s] = t
      end
      return t
    end
end)()

自执行函数的优点在于您只需要定义一次expensive函数,但缺点是它比do/end块稍微难读。否则它们几乎是相同的。

2017-05-18 22:44:39
用户1442917
用户1442917

你可以使用“记忆化”来缓存函数根据参数返回的值。您可以阅读《Lua编程》中的一章,并使用其中一个为您处理工作的记忆化模块,例如memoize

此外,还可以参见以下SO答案以获取相关有趣的解决方案。

2017-05-19 05:04:15