{"id":16570301,"url":"https://github.com/benibela/hamt","last_synced_at":"2026-03-09T15:05:16.934Z","repository":{"id":151264672,"uuid":"146897650","full_name":"benibela/hamt","owner":"benibela","description":"Mutable and immutable persistent maps and sets as hash array mapped trie (HAMT) for FreePascal","archived":false,"fork":false,"pushed_at":"2020-04-25T22:49:41.000Z","size":113,"stargazers_count":17,"open_issues_count":0,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-05T12:48:05.990Z","etag":null,"topics":["hamt","hashmap","hashset","hat-trie","immutable","immutable-collections","immutable-datastructures","map","persistent-data-structure","set","trie"],"latest_commit_sha":null,"homepage":"https://www.benibela.de/documentation/hamt/bbhamt.html","language":"Pascal","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/benibela.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-31T13:45:24.000Z","updated_at":"2024-10-22T11:23:32.000Z","dependencies_parsed_at":"2023-05-05T00:36:19.225Z","dependency_job_id":null,"html_url":"https://github.com/benibela/hamt","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/benibela/hamt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benibela%2Fhamt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benibela%2Fhamt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benibela%2Fhamt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benibela%2Fhamt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benibela","download_url":"https://codeload.github.com/benibela/hamt/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benibela%2Fhamt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30299912,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T14:33:48.460Z","status":"ssl_error","status_checked_at":"2026-03-09T14:33:48.027Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["hamt","hashmap","hashset","hat-trie","immutable","immutable-collections","immutable-datastructures","map","persistent-data-structure","set","trie"],"created_at":"2024-10-11T21:18:20.567Z","updated_at":"2026-03-09T15:05:16.885Z","avatar_url":"https://github.com/benibela.png","language":"Pascal","readme":"Hash Array Mapped Trie (HAMT)\n============\n\nA HAMT is a hashmap/set stored as trie, which provides update and lookup performance similarly to a normal hashmap/set, but needs no rehashing and also allows one to copy the entire map/set in constant time.  This implementation uses a 32 bit hash and trie nodes with 32 children, so 5 bits of the hash are consumed to choose the next child. When there are no hash collisions, this HAMT can store 2^32 items with a maximal tree depth of (log_32 2^32) = 6, i.e., you need 6 memory accesses to find any key/value which is practically O(1). Although when there are hash collisions, they are put in an array. \n\nEach HAMT node carries a reference counter, since FreePascal has no garbage collector. If the reference count is 1, the node can mutate, otherwise it is immutable with a copy-on-write semantic like strings. The counter is updated atomically, so the map could be shared across threads. This might lead to a large number of memory writes when a path of a full tree is copied (6 levels of up 32 children), but still less than copying a full hash table.\n\nEverything is implemented using generics, so it can be used with all types.\n\nExamples\n------------\n\nMutable Map:\n\n```pascal\ntype TMutableMapStringString = specialize TMutableMap\u003cstring, string, THAMTTypeInfo\u003e;\nvar map: TMutableMapStringString;\n    p: TMutableMapStringString.PPair;\nbegin\n  map := TMutableMapStringString.create;\n  map.Insert('hello', 'world');\n  map.insert('foo', 'bar');\n  map['abc'] := 'def';\n\n  writeln(map['hello']); // world\n  writeln(map.get('foo')); // bar\n  writeln(map.get('abc', 'default')); // def\n\n  //enumerate all\n  for p in map do\n    writeln(p^.key, ': ', p^.value);\n\n  map.free;\nend.\n```\n\nImmutable Map:\n\n\n```pascal\ntype TImmutableMapStringString = specialize TImmutableMap\u003cstring, string, THAMTTypeInfo\u003e;\nvar map, map2, map3: TImmutableMapStringString;\n    p: TImmutableMapStringString.PPair;\nbegin\n  map := TImmutableMapStringString.create;\n  map2 := map.Insert('hello', 'world');\n  map3 := map2.insert('foo', 'bar');\n\n  writeln(map.get('hello', 'default')); // default\n  writeln(map.get('foo', 'default')); // default\n\n  writeln(map2.get('hello')); // world\n  writeln(map2.get('foo', 'default')); // default\n\n  writeln(map3['hello']); // world\n  writeln(map3['foo']); // bar\n\n  //enumerate all\n  for p in map3 do\n    writeln(p^.key, ': ', p^.value);\n\n  map.free;\n  map2.free;\n  map3.free;\nend.\n```\n\nMutable Set:\n```pascal\ntype TMutableSetString = specialize TMutableSet\u003cstring, THAMTTypeInfo\u003e;\nvar stringSet: TMutableSetString;\n    p: TMutableSetString.PItem;\nbegin\n  stringSet := TMutableSetString.create;\n  stringSet.Insert('hello');\n  stringSet.insert('foo');\n\n  writeln(stringSet['hello']); // true\n  writeln(stringSet.contains('foo')); // true\n  writeln(stringSet.contains('abc')); // false\n\n  //enumerate all\n  for p in stringSet do\n    writeln(p^);\n\n  stringSet.free;\nend.\n```\n\n\nImmutable Set:\n\n```pascal\ntype TImmutableSetString = specialize TImmutableSet\u003cstring, THAMTTypeInfo\u003e;\nvar set1, set2, set3: TImmutableSetString;\n  p: TImmutableSetString.PItem;\nbegin\n  set1 := TImmutableSetString.create;\n  set2 := set1.Insert('hello');\n  set3 := set2.insert('foo');\n\n  writeln(set1.contains('hello')); // false\n  writeln(set1['foo']);            // false\n\n  writeln(set2.contains('hello')); // true\n  writeln(set2['foo']);            // false\n\n  writeln(set3.contains('hello')); // true\n  writeln(set3['foo']);            // true\n\n  //enumerate all\n  for p in set3 do\n    writeln(p^);\n\n  set1.free;\n  set2.free;\n  set3.free;\nend.\n```\n\n\nDocumentation\n--------\n\nManual: \n\n\n* [Maps](https://www.benibela.de/documentation/hamt/hamt.maps.html)\n\n* [Sets](https://www.benibela.de/documentation/hamt/hamt.sets.html)\n\n* [HAMT](https://www.benibela.de/documentation/hamt/hamt.internals.html)\n\nInstallation\n---------\nThis library requires no installation, there are no dependencies besides the FreePascal compiler. Just copy the `hamt.*` files in the unit search path of FreePascal.  Then you can use the maps with `uses hamt.maps` and the sets with `uses hamt.sets`.\n\nHowever, beware that the last stable release of FreePascal, 3.0.4, cannot compile the complex generics used here. You need to have at least FreePascal 3.1.1, preferably 3.3.1 with revision r39690.\n \nTo run the tests cases in `tests/hamt_tests.pas`, you also need to have [bbutils](https://www.benibela.de/sources_en.html#bbutils) in the search path.\n \n\n \nReferences\n-------\n[Ideal Hash Trees](https://infoscience.epfl.ch/record/64398/files/idealhashtrees.pdf)\n\n[Efficient Immutable Collections](https://michael.steindorfer.name/publications/phd-thesis-efficient-immutable-collections.pdf)\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenibela%2Fhamt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenibela%2Fhamt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenibela%2Fhamt/lists"}