198 lines
4.9 KiB
Plaintext
198 lines
4.9 KiB
Plaintext
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 |