Compare commits
2 Commits
2a2936ef02
...
0d2db659ca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d2db659ca | ||
|
|
5f1233a393 |
198
sketching/september_2025/map/Map.dm
Normal file
198
sketching/september_2025/map/Map.dm
Normal 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
|
||||
Loading…
Reference in New Issue
Block a user