diff --git a/CHANGELOG.md b/CHANGELOG.md index 97db594..7dc0989 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased +- The `gleam/erlang` module gains the `hash` and + `bounded_hash` functions. + ## v0.30.0 - 2024-11-11 - The `gleam/erlang/process` module gains the `deselecting` function. diff --git a/src/gleam/erlang.gleam b/src/gleam/erlang.gleam index 7d34ce4..84f5c13 100644 --- a/src/gleam/erlang.gleam +++ b/src/gleam/erlang.gleam @@ -206,3 +206,19 @@ pub fn reference_from_dynamic( /// @external(erlang, "gleam_erlang_ffi", "priv_directory") pub fn priv_directory(name: String) -> Result(String, Nil) + +/// Portable hash function that gives the same hash for the +/// same Gleam/Erlang term regardless of machine architecture and +/// ERTS version. +/// +/// The function returns a hash value for Term within the range 0..limit-1. +/// The maximum value for limit is 2^32. +/// +/// +@external(erlang, "erlang", "phash2") +pub fn bounded_hash(term: anything, limit limit: Int) -> Int + +/// Equivalent to hash_range. +/// Returns a value in the range 0..2^27-1 +@external(erlang, "erlang", "phash2") +pub fn hash(term: anything) -> Int diff --git a/test/gleam/erlang_test.gleam b/test/gleam/erlang_test.gleam index 390ccf2..dc0f1f3 100644 --- a/test/gleam/erlang_test.gleam +++ b/test/gleam/erlang_test.gleam @@ -79,3 +79,15 @@ pub fn priv_directory_test() { let assert Ok(dir) = erlang.priv_directory("gleam_stdlib") let assert True = string.ends_with(dir, "/gleam_stdlib/priv") } + +pub fn bounded_hash_test() { + let assert 9 = erlang.bounded_hash("hello", limit: 10) + let assert 0 = erlang.bounded_hash([5, 2, 8], limit: 10) + let assert 82 = erlang.bounded_hash(Ok(#("testing", 123)), limit: 200) +} + +pub fn hash_test() { + let assert 47_480_723 = erlang.hash("hello") + let assert 79_761_634 = erlang.hash([5, 2, 8]) + let assert 133_777_698 = erlang.hash(Ok(#("testing", 123))) +}