_memoize.lua 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. --- Module for private utility functions
  2. --- @param argc integer?
  3. --- @return fun(...): any
  4. local function concat_hash(argc)
  5. return function(...)
  6. return table.concat({ ... }, '%%', 1, argc)
  7. end
  8. end
  9. --- @param idx integer
  10. --- @return fun(...): any
  11. local function idx_hash(idx)
  12. return function(...)
  13. return select(idx, ...)
  14. end
  15. end
  16. --- @param hash integer|string|fun(...): any
  17. --- @return fun(...): any
  18. local function resolve_hash(hash)
  19. if type(hash) == 'number' then
  20. hash = idx_hash(hash)
  21. elseif type(hash) == 'string' then
  22. local c = hash == 'concat' or hash:match('^concat%-(%d+)')
  23. if c then
  24. hash = concat_hash(tonumber(c))
  25. else
  26. error('invalid value for hash: ' .. hash)
  27. end
  28. end
  29. --- @cast hash -integer
  30. return hash
  31. end
  32. --- @generic F: function
  33. --- @param hash integer|string|fun(...): any
  34. --- @param fn F
  35. --- @param strong? boolean
  36. --- @return F
  37. return function(hash, fn, strong)
  38. vim.validate('hash', hash, { 'number', 'string', 'function' })
  39. vim.validate('fn', fn, 'function')
  40. ---@type table<any,table<any,any>>
  41. local cache = {}
  42. if not strong then
  43. setmetatable(cache, { __mode = 'kv' })
  44. end
  45. hash = resolve_hash(hash)
  46. return function(...)
  47. local key = hash(...)
  48. if cache[key] == nil then
  49. cache[key] = vim.F.pack_len(fn(...))
  50. end
  51. return vim.F.unpack_len(cache[key])
  52. end
  53. end