Skip to content

Commit

Permalink
Merge branch 'main' into trig-func-special-input
Browse files Browse the repository at this point in the history
  • Loading branch information
Kaida-Amethyst authored Dec 23, 2024
2 parents ca31541 + c234aaf commit 6e86abe
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 9 deletions.
41 changes: 36 additions & 5 deletions builtin/linked_hash_map.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -184,16 +184,47 @@ pub fn op_get[K : Hash + Eq, V](self : Map[K, V], key : K) -> V? {
}

///|
/// Get the value associated with a key,
/// returns the provided default value if the key does not exist.
/// Returns the value associated with the key in the map, or computes and returns
/// a default value if the key does not exist.
///
/// Parameters:
///
/// * `map` : The map to search in.
/// * `key` : The key to look up in the map.
/// * `default` : A function that returns a default value when the key is not
/// found.
///
/// Returns either the value associated with the key if it exists, or the result
/// of calling the default function.
///
/// Example:
///
/// ```moonbit
/// test "get_or_default" {
/// let map = { "a": 1, "b": 2 }
/// inspect!(map.get_or_default("a", 0), content="1")
/// inspect!(map.get_or_default("c", 42), content="42")
/// }
/// ```
pub fn get_or_default[K : Hash + Eq, V](
self : Map[K, V],
key : K,
default : V
) -> V {
match self.get(key) {
Some(v) => v
None => default
let hash = key.hash()
for i = 0, idx = hash & self.capacity_mask {
match self.entries[idx] {
Some(entry) => {
if entry.hash == hash && entry.key == key {
break entry.value
}
if i > entry.psl {
break default
}
continue i + 1, (idx + 1) & self.capacity_mask
}
None => break default
}
}
}

Expand Down
50 changes: 46 additions & 4 deletions hashmap/hashmap.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,12 @@ pub fn op_set[K : Hash + Eq, V](self : T[K, V], key : K, value : V) -> Unit {
///|
/// Get the value associated with a key.
pub fn get[K : Hash + Eq, V](self : T[K, V], key : K) -> V? {
let hash = key.hash()
self.get_with_hash(key, key.hash())
}

///|
fn get_with_hash[K : Hash + Eq, V](self : T[K, V], key : K, hash : Int) -> V? {
for i = 0, idx = hash & (self.capacity - 1) {
// if i == self.capacity {
// panic()
// }
match self.entries[idx] {
Some(entry) => {
if entry.hash == hash && entry.key == key {
Expand All @@ -126,6 +127,47 @@ pub fn op_get[K : Hash + Eq, V](self : T[K, V], key : K) -> V? {
self.get(key)
}

///|
/// Gets the value associated with the given key. If the key doesn't exist in the
/// map, initializes it with the result of calling the provided initialization
/// function.
///
/// Parameters:
///
/// * `self` : The hash map.
/// * `key` : The key to look up in the map.
/// * `init` : A function that takes no arguments and returns a value to be
/// associated with the key if it doesn't exist.
///
/// Returns the value associated with the key, either existing or newly
/// initialized.
///
/// Example:
///
/// ```moonbit
/// test "get_or_init" {
/// let map : @hashmap.T[String, Int] = @hashmap.new()
/// let value = map.get_or_init("key", fn() { 42 })
/// inspect!(value, content="42")
/// inspect!(map.get("key"), content="Some(42)")
/// }
/// ```
pub fn get_or_init[K : Hash + Eq, V](
self : T[K, V],
key : K,
init : () -> V
) -> V {
let hash = key.hash()
match self.get_with_hash(key, hash) {
Some(v) => v
None => {
let v = init()
self.set_with_hash(key, v, hash)
v
}
}
}

///|
/// Get the value associated with a key,
/// returns the provided default value if the key does not exist.
Expand Down
1 change: 1 addition & 0 deletions hashmap/hashmap.mbti
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ impl T {
from_iter[K : Hash + Eq, V](Iter[(K, V)]) -> Self[K, V]
get[K : Hash + Eq, V](Self[K, V], K) -> V?
get_or_default[K : Hash + Eq, V](Self[K, V], K, V) -> V
get_or_init[K : Hash + Eq, V](Self[K, V], K, () -> V) -> V
is_empty[K, V](Self[K, V]) -> Bool
iter[K, V](Self[K, V]) -> Iter[(K, V)]
iter2[K, V](Self[K, V]) -> Iter2[K, V]
Expand Down
21 changes: 21 additions & 0 deletions hashmap/hashmap_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,24 @@ test "from_iter empty iter" {
let map : @hashmap.T[Int, Int] = @hashmap.T::from_iter(Iter::empty())
inspect!(map, content="HashMap::of([])")
}

test "@hashmap.contains/empty" {
let map : @hashmap.T[Int, String] = @hashmap.T::new()
inspect!(map.contains(42), content="false")
}

test "@hashmap.contains/basic" {
let map = @hashmap.T::of([(1, "one"), (2, "two"), (3, "three")])
inspect!(map.contains(2), content="true")
inspect!(map.contains(4), content="false")
}

test "@hashmap.contains/after_operations" {
let map = @hashmap.T::of([(1, "one"), (2, "two")])
map.remove(1)
inspect!(map.contains(1), content="false")
map.set(1, "ONE")
inspect!(map.contains(1), content="true")
map.clear()
inspect!(map.contains(2), content="false")
}

0 comments on commit 6e86abe

Please sign in to comment.