{"id":13735749,"url":"https://github.com/andreaferretti/memo","last_synced_at":"2025-04-10T20:12:39.564Z","repository":{"id":34209532,"uuid":"38066577","full_name":"andreaferretti/memo","owner":"andreaferretti","description":"Memoization for Nim","archived":false,"fork":false,"pushed_at":"2022-02-25T11:14:12.000Z","size":16,"stargazers_count":79,"open_issues_count":5,"forks_count":10,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-24T17:53:10.682Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andreaferretti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-06-25T18:28:21.000Z","updated_at":"2025-02-10T09:54:23.000Z","dependencies_parsed_at":"2022-09-12T13:51:28.750Z","dependency_job_id":null,"html_url":"https://github.com/andreaferretti/memo","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreaferretti%2Fmemo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreaferretti%2Fmemo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreaferretti%2Fmemo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreaferretti%2Fmemo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andreaferretti","download_url":"https://codeload.github.com/andreaferretti/memo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248288362,"owners_count":21078903,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T03:01:10.649Z","updated_at":"2025-04-10T20:12:39.545Z","avatar_url":"https://github.com/andreaferretti.png","language":"Nim","readme":"Memoize Nim functions\n=====================\n\n[![Build Status](https://travis-ci.org/andreaferretti/memo.svg?branch=master)](https://travis-ci.org/andreaferretti/memo)\n[![nimble](https://raw.githubusercontent.com/yglukhov/nimble-tag/master/nimble_js.png)](https://github.com/yglukhov/nimble-tag)\n\nThis small package offers a function and a macro to memoize Nim functions.\n\nUsage\n-----\n\nIf `f(a: A): B` is a function, one can obtain a memoized version of `f` by doing\n\n```nim\nimport memo\nlet g = memoize(f)\n```\n\n`g` will then be equivalent to `f` (modulo side effects), but results of calling `g`\nwill be cached. The function `memoize` can be used on any function, but will not\nhandle correctly recursive functions, as self calls of `f`, both direct and indirect,\nwill still keep refering to the non-memoize version of `f`.\n\nIf you have access to the definition of `f`, one can do better with the `memoized`\nmacro. Usage is as follows:\n\n```nim\nimport memo\nproc f(a: A): B {.memoized.} =\n  ...\n```\n\nThen `f` will be memoized and recursive calls will be handled correctly (both\ndirect self-recursion and mutual recursion).\n\nExample\n-------\n\n```nim\nimport memo\n\nproc fib(n : int) : int {.memoized.} =\n  if n \u003c 2: n\n  else: fib(n-1) + fib(n-2)\n\nwhen isMainModule:\n  echo fib(40)\n```\n\nThis small program returns very fast, while without the `memoized` pragma, it takes\na few seconds before producing a result. For an example of mutual recursive functions\n\n```nim\nimport memo\n\nproc fib(n : int) : int\n\nproc fib1(n : int) : int {.memoized.} =\n  if n \u003c 2: n\n  else: fib(n-1) + fib(n-2)\n\nproc fib(n : int) : int {.memoized.} =\n  if n \u003c 2: n\n  else: fib1(n-1) + fib1(n-2)\n\nwhen isMainModule:\n  echo fib(80)\n```\n\nRestrictions\n------------\n\n* `memoize` function, as opposed to `memoized` macro, can only memoize functions\n  of a single argument, altough one can convert any function in this form by using\n  a tuple argument\n* types of all arguments have to implement ``hash``, since they will be used as\n  parts of a key in a hashtable\n\nAn example of the first issue would be memoizing the Levenshtein distance for\nstrings, as it is a function of two arguments. It can be done like this:\n\n```nim\nimport memo\n\ntemplate tail(s: string): string = s[1 .. s.high]\n\ntemplate head(s: string): char = s[0]\n\n# `memoized` macro handles multiple arguments:\nproc lev(a: string, b: string): int {.memoized.} =\n  if a.len == 0: return b.len\n  if b.len == 0: return a.len\n  let\n    d1 = lev(a.tail, b) + 1\n    d2 = lev(a, b.tail) + 1\n    d3 = lev(a.tail, b.tail) + (if a.head == b.head: 0 else: 1)\n  result = min(min(d1, d2), d3)\n\n# `memoize` function does not:\ntemplate memTwoArg =\n  let levMem: proc(int): int = memoize(lev)\nassert: not compiles memTwoArg\n\nwhen isMainModule:\n  echo levenshtein(\"submarine\", \"subreddit\")\n```\n\nResetting the cache\n-------------------\n\nThe `{.memoized.}` macro also generates a function that can be used to reset the\ncache where previous results are stored. If `name` is the name of the function,\nthe auxiliary function to reset the cache is called `resetCacheName`.\n\nThus, you can do the following\n```nim\nproc fib(n : int) : int {.memoized.} =\n  if n \u003c 2: n\n  else: fib(n-1) + fib(n-2)\n\necho fib(40)\nresetCacheFib()\necho fib(50)\n```\n\nThis allows to avoid memory leaks by accumulating too many values in the cache.","funding_links":[],"categories":["Language Features"],"sub_categories":["Macros"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreaferretti%2Fmemo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandreaferretti%2Fmemo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreaferretti%2Fmemo/lists"}