在 Lua 中的单独函数调用之间缓存对字符串的昂贵表计算

rus*_*a6f 5 lua

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

local function expensive(s)
  local t = nil
  return function()
    if not t then
      t = {}
      -- some expensive operations with s which add items to t
    end
    return t
  end
end

local function fn1(s)
  local t = expensive(s)
  -- some other fast operations using t and s
end

local function fn2(s)
  local t = expensive(s)
  -- some other fast operations using t and s
end

local s1, s2 = 'a', 'b'
fn1(s1) -- should create the 't' table for s1
fn1(s2) -- should create the 't' table for s2
fn2(s1) -- should not create the 't' table again for s1
fn1(s2) -- should also not create the 't' table again for s2
Run Code Online (Sandbox Code Playgroud)

我怎样才能让昂贵的函数为每个字符串只创建一次表,在任何一种情况下都返回表?我宁愿不让桌子暴露在全球环境中。我认为这可能可以通过巧妙地使用闭包来完成,但我不太了解这个结构。

Jac*_*lor 2

叶戈尔的答案可以完成这项工作,但cache整个文件都可以访问该表。要隐藏它,您有几种选择。第一个是简单的 do/end 块。

local expensive
do
    local cache = {}
    expensive = function (s)
      local t = cache[s]
      if not t then
        t = {}
        -- some expensive operations with s which add items to t
        cache[s] = t
      end
      return t
    end
end
Run Code Online (Sandbox Code Playgroud)

另一个是自执行函数。

local expensive = (function ()
    local cache = {}
    return function (s)
      local t = cache[s]
      if not t then
        t = {}
        -- some expensive operations with s which add items to t
        cache[s] = t
      end
      return t
    end
end)()
Run Code Online (Sandbox Code Playgroud)

自执行函数的优点是只需定义expensive一次函数名,但缺点是比 do/end 块更难阅读。否则它们几乎是一样的。