Compare commits

..

2 Commits

Author SHA1 Message Date
Jesse Brault
0d2db659ca Work on Map sketching and related. 2025-09-24 12:33:48 -05:00
Jesse Brault
5f1233a393 Sketch HashMap impl. 2025-09-23 20:04:26 -05:00

View File

@ -0,0 +1,198 @@
pub trait Functor<T>[Self<T>]
fn map(mapper: fn (t: &T) -> U) -> Self<U>
end
pub trait Sum<T>
fn sum() -> T
end
pub trait Default
fn default() -> Self
end
pub trait Iter<T>
ref fn iter() -> Iterator<&T>
end
pub trait ConsIter<T>
cons fn consIter() -> Iterator<T>
end
pub int Iterator<T>
fn next() -> Option<T>
end
pub int List<T> impl Functor<T>, Iter<T>, ConsIter<T>
fn add(t: T) -> Void
end
pub class ArrayList<T> : List<T>
let mut currentIndex = 0
let mut inner: Array<T>
ctor(capacity: Int) where T impl Default
inner = Array(capacity, Default[T])
end
ctor(capacity: Int, init: fn () -> T)
inner = Array(capacity, init)
end
impl fn add(t: T) -> Void
inner[currentIndex] = t
let currentCapacity = inner.capacity()
currentIndex++
if currentIndex == currentCapacity then
let oldInner = std::mem::take(inner, Array(currentCapacity * 2))
arrays::copy(oldInner, inner)
end
end
end
impl Functor[ArrayList<*>]
fn map(mapper: fn (t: &T) -> U) -> Self<U>
let mut result: Array<U> = Array(inner.capacity)
for (i, t) in inner.iterWithIndex() do
result[i] = mapper(t)
end
result
end
end
impl Sum[Self = List<Int>, T = Int]
fn sum() -> Int
let mut result = 0
for value in self do
result += value
end
result
end
end
impl<T impl Default> Default[ArrayList<T>]
const DEFAULT_SIZE = 10
static fn default() -> Self = ArrayList(DEFAULT_SIZE, Default[T]::default)
end
impl<T> Iter[ArrayList<T>]
ref fn iter() -> Iterator<&T>
let mut currentIndex = 0
return {
if currentIndex < inner.count() then
let item = inner[currentIndex]
currentIndex++
Some(item)
else
None
end
}
end
end
impl<T impl Default> ConsIter[ArrayList<T>]
cons fn consIter() -> Iterator<T>
let mut currentIndex = 0
let inner = std::mem::take(inner, std::arrays::empty())
return |inner| {
if currentIndex < inner.count() then
let item = inner.take(currentIndex, Default[T]::default)
currentIndex++
Some(item)
else
None
end
}
end
end
pub enum Option<T>
Some(t: T),
None
end
impl Default[Option<*>]
static fn default() -> Self = None
end
pub trait HashCode
fn hash() -> USize
end
pub int Map<K, V>
fn get(key: K) -> Option<&V>
fn put(key: K, value: V) -> Void
fn take(key: K) -> Option<V>
end
pub class HashMap<K, V> : Map<K, V>
where K impl HashCode
const LOAD_FACTOR = 0.8
class Entry<K, V>(pub key: K, pub value: V) end
let mut buckets: List<List<Option<Entry<K, V>>>> = ArrayList(10)
fn getBucketIndex(key: K) -> Int
HashCode[K].hash(key) % buckets.size()
end
fn getCount() -> Int = buckets.map { it.count() }.sum::<Int>()
fn getCapacity() -> Int = buckets.map { it.capacity() }.sum::<Int>()
fn redistribute()
use std::mem::take
let oldBucketCapacity = buckets.first().unwrap().capacity()
let oldBuckets = take(buckets, ArrayList(oldBucketCapacity * 2))
for bucket in oldBuckets.consIter() do
for entry in bucket.consIter() do
let newIndex = getBucketIndex(entry.key)
let newBucket = buckets[newIndex]
newBucket.add(Entry(entry.key, entry.value))
end
end
end
impl fn put(key: K, value: V) -> Void
let bucket = buckets[getBucketIndex(key)]
bucket.add(Entry(key, value))
if getCount() / getCapacity() > LOAD_FACTOR then
redistribute()
end
end
impl fn get(key: K) -> Option<&V>
let bucket = buckets[getBucketIndex(key)] // bucket: &List<Entry<K, V>>
bucket.find { it.key == key } // it: &Entry<K, V>
.map { it.value } // it.value: &V
end
impl fn take(key: K) -> Option<V>
let mut bucket = buckets.take(getBucketIndex(key)) // bucket: List<Entry<K, V>>
if bucket.findIndex { it.key == key } is Some(index) then
let entry = bucket.take(index) // entry: Entry<K, V>
Some(entry.value) // moved out of Entry
else
None
end
end
end
impl HashCode for String
fn hash() -> Int = todo()
end
class Greeter(pub greeting: String) end
fn main()
let greeterMap: Map<String, Greeter> = HashMap()
greeterMap.put("friendly", Greeter("Friendly hello!"))
greeterMap.put("nasty", Greeter("Nasty hello!"))
let friendlyGreeter: &Greeter = greeterMap.get("friendly").unwrap()
println friendlyGreeter.greeting
let nastyGreeter: Greeter = greeterMap.take("nasty").unwrap()
println nastyGreeter.greeting
end