Skip to content

Commit 0a0400a

Browse files
committed
add get_by_view method to Map
1 parent c36e392 commit 0a0400a

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

builtin/builtin.mbti

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ impl Map {
269269
from_array[K : Hash + Eq, V](Array[(K, V)]) -> Self[K, V]
270270
from_iter[K : Hash + Eq, V](Iter[(K, V)]) -> Self[K, V]
271271
get[K : Hash + Eq, V](Self[K, V], K) -> V?
272+
get_by_view[K, View : Hash + Eq, Value](Self[K, Value], View, view~ : (K) -> View) -> Value?
272273
get_or_default[K : Hash + Eq, V](Self[K, V], K, V) -> V
273274
get_or_init[K : Hash + Eq, V](Self[K, V], K, () -> V) -> V
274275
is_empty[K, V](Self[K, V]) -> Bool

builtin/linked_hash_map.mbt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,35 @@ pub fn Map::get[K : Hash + Eq, V](self : Map[K, V], key : K) -> V? {
194194
}
195195
}
196196
197+
///|
198+
/// Get the value associated with the view of a key.
199+
/// When searching the map, instead of comparing keys directly,
200+
/// a view of keys, obtained by the parameter `view`, is used.
201+
/// This is useful for e.g. querying a `Map` of `String` with `@string.View`.
202+
///
203+
/// The `view` function and the `Hash` implementation of `View` should satisfy:
204+
/// ```skip
205+
/// view(key).hash() == key.hash()
206+
/// ```
207+
#locals(view)
208+
pub fn Map::get_by_view[K, View : Hash + Eq, Value](
209+
self : Map[K, Value],
210+
key : View,
211+
view~ : (K) -> View
212+
) -> Value? {
213+
let hash = key.hash()
214+
for i = 0, idx = hash & self.capacity_mask {
215+
guard self.entries[idx] is Some(entry) else { break None }
216+
if entry.hash == hash && view(entry.key) == key {
217+
break Some(entry.value)
218+
}
219+
if i > entry.psl {
220+
break None
221+
}
222+
continue i + 1, (idx + 1) & self.capacity_mask
223+
}
224+
}
225+
197226
///|
198227
#deprecated("Use `get` instead. `op_get` will return `V` instead of `Option[V]` in the future.")
199228
pub fn Map::op_get[K : Hash + Eq, V](self : Map[K, V], key : K) -> V? {

builtin/linked_hash_map_test.mbt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,21 @@ test "map::contains_kv" {
6060
}
6161

6262
}
63+
64+
///|
65+
test "map::get_by_view::string_view" {
66+
let map = { "a": 1, "b": 2, "c": 3 }
67+
let str = "abcd"
68+
fn slice(s : String, i, j) {
69+
s.charcodes(start=i, end=j)
70+
}
71+
72+
fn view(s : String) {
73+
s[:]
74+
}
75+
76+
inspect!(map.get_by_view(slice(str, 0, 1), view~), content="Some(1)")
77+
inspect!(map.get_by_view(slice(str, 1, 2), view~), content="Some(2)")
78+
inspect!(map.get_by_view(slice(str, 2, 3), view~), content="Some(3)")
79+
inspect!(map.get_by_view(slice(str, 3, 4), view~), content="None")
80+
}

0 commit comments

Comments
 (0)