pub trait Functor[Self] fn map(mapper: fn (t: &T) -> U) -> Self end pub trait Sum fn sum() -> T end pub trait Default fn default() -> Self end pub trait Iter ref fn iter() -> Iterator<&T> end pub trait ConsIter cons fn consIter() -> Iterator end pub int Iterator fn next() -> Option end pub int List impl Functor, Iter, ConsIter fn add(t: T) -> Void end pub class ArrayList : List let mut currentIndex = 0 let mut inner: Array 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 let mut result: Array = Array(inner.capacity) for (i, t) in inner.iterWithIndex() do result[i] = mapper(t) end result end end impl Sum[Self = List, T = Int] fn sum() -> Int let mut result = 0 for value in self do result += value end result end end impl Default[ArrayList] const DEFAULT_SIZE = 10 static fn default() -> Self = ArrayList(DEFAULT_SIZE, Default[T]::default) end impl Iter[ArrayList] 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 ConsIter[ArrayList] cons fn consIter() -> Iterator 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 Some(t: T), None end impl Default[Option<*>] static fn default() -> Self = None end pub trait HashCode fn hash() -> USize end pub int Map fn get(key: K) -> Option<&V> fn put(key: K, value: V) -> Void fn take(key: K) -> Option end pub class HashMap : Map where K impl HashCode const LOAD_FACTOR = 0.8 class Entry(pub key: K, pub value: V) end let mut buckets: List>>> = ArrayList(10) fn getBucketIndex(key: K) -> Int HashCode[K].hash(key) % buckets.size() end fn getCount() -> Int = buckets.map { it.count() }.sum::() fn getCapacity() -> Int = buckets.map { it.capacity() }.sum::() 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> bucket.find { it.key == key } // it: &Entry .map { it.value } // it.value: &V end impl fn take(key: K) -> Option let mut bucket = buckets.take(getBucketIndex(key)) // bucket: List> if bucket.findIndex { it.key == key } is Some(index) then let entry = bucket.take(index) // entry: Entry 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 = 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